【问题标题】:Secure way to pass a parameter from view to controller and returning it as a view将参数从视图传递到控制器并将其作为视图返回的安全方法
【发布时间】:2014-06-26 22:49:30
【问题描述】:

我正在寻找查询字符串的安全替代方案,我将在同一控制器上将参数传递给控制器​​方法并将其作为视图返回。

类别视图:

@foreach (Project.Framework.ModelClasses.productCategories productCategories in ViewBag.Categories)
    {           
        @Html.ActionLink(productCategories.description, "Products", "Shop", new { id = "", categoryID = productCategories.categoryID, description = productCategories.description }, null)
    }

控制器方法:

public ActionResult Products(string categoryID, string keyword, string description)
    {
        ViewBag.appPath = ConfigurationManager.AppSettings["appPath"].ToString();
        Methods Methods = new Methods();
        Methods.tokenHeader = (string)Session["token"];
        Methods.cookieContainer = (CookieContainer)Session["cookies"];

        Response shopnowProductsResponse = Methods.shopnowProductsGet(categoryID, keyword);
        if (shopnowProductsResponse.Code == "000")
        {
            List<product> products = new List<product>();
            products = (List<product>)shopnowProductsResponse.Data;

            string FPRFlag = "0";
            foreach (product product in products)
            {
                if (FPRFlag != "1")
                {
                    if (product.FPRFlag == "1")
                    {
                        FPRFlag = product.FPRFlag;
                    }
                }
                else
                {
                    goto nextState;
                }
            }
        nextState:

            ViewBag.FPRFlag = FPRFlag;
            ViewBag.Description = description;
            ViewBag.Products = products;
        }

        return View();
    }

注意:关键字是可选的

【问题讨论】:

  • 您在问题中使用的“安全”是什么意思? (也许签署数据可以解决它?)
  • 特别是,如果它是 URL 的一部分而不是查询字符串,它是否足够安全?让它成为路线的一部分?
  • 出于安全原因,我无法通过 URL 传递任何参数,因为我正在传递敏感数据。
  • 定义“安全”。您需要对用户隐藏它吗?对监控流量的人隐瞒?您是否需要能够进行完整性检查? “安全”意味着很多东西。
  • 如果是敏感数据,那么你应该把它保存在服务器端并放在会话中。根据定义,您发送给客户端(浏览器)的任何内容都是不安全的。您当然可以对其进行加密,但是当您可以将其保留在服务器端时,为什么还要经历所有这些麻烦呢。

标签: c# asp.net-mvc parameter-passing


【解决方案1】:

假设您只想对这些链接进行编码,以使最终用户无法从 URL 中抓取所有产品数据的列表,您可以通过在链接中使用替代代码来实现此目的。我会使用哈希值:

@foreach (Project.Framework.ModelClasses.productCategories category in ViewBag.Categories)
{
    @Html.ActionLink(category.description, "Products", "Shop", 
        new { 
            hc = category.categoryID.GetHashCode() 
        })
}

然后在控制器中查找哈希码而不是 categoryID

这仍然留下两个问题:

  1. 哈希码将显示在浏览器的地址栏上。
  2. 哈希码列表每次都相同。

第一个问题可以通过将哈希码转换回categoryID并将结果存储在Session存储中,然后重定向到Products页面的中间操作来修复:

public ActionResult SetCategory(int hc)
{
    string catID = HashToCategoryID(hc);
    Session["categoryID"] = catID;
    return RedirectToAction("Products");
}

这不仅将用户的浏览器返回到Products 页面,还确保(在大多数情况下)SetCategory URL 甚至不会出现在浏览器历史记录中。一般来说,浏览器历史记录甚至不会显示它一开始就离开了Products 页面,因此点击Back 按钮会将它们从页面带到他们第一次进入之前的任何位置。

另一个问题 - 哈希码不改变 - 可以通过两种方式修复:用一个会随着访问而改变的值(如会话 ID)对哈希进行加盐处理,或者生成随机值并将它们存储在 @987654331 @storage 用于查找。

例如:

// after loading your products:

// something to salt the hash codes with:
string salt = (DateTime.Now - DateTime.Today).TotalMilliseconds.ToString();

// generate hash codes for all the product categories
var hashcodes = products.Select(p => new { h = (salt + p.categoryID).HashCode(), c = p.categoryID });

// create hash->categoryID dictionary and save in Session
var hashtocat = hashcodes.ToDictionary(hc => hc.h, hc => hc.c);
Session["HashToCategory"] = hashtocat;

// create categoryID->hash dictionary and save in ViewBag
var cattohash = hashcodes.ToDictionary(hc => hc.c, hc => hc.h);
ViewBag["CategoryToHash"] = cattohash; 

现在每次加载页面时,您都会得到一组不同的哈希值。然后您的链接生成变为:

@{ // grab hashcode dictionary from ViewBag
    Dictionary<string, int> hashcodes = ViewBag["CategoryToHash"] as Dictionary<string, int>;
}

@foreach (Project.Framework.ModelClasses.productCategories category in ViewBag.Categories)
{
    @Html.ActionLink(product.description, "SetCategory", new { hc = hashcodes[product.categoryID] })
}

实际上,您现在有一个一次性代码列表,该列表在用户每次重新访问Products 页面时都会过期并被新代码替换。使相同的代码在同一类别中多次运行的可能性很小,除非从同一会话中单击链接,否则它将失败。

说到失败...您需要在其中添加一堆错误处理。

【讨论】:

  • 在此回复之前。这是我的项目中所做的,但没有使用哈希。谢谢您的回答。现在我在考虑浏览器中的用户是否有可能进入此方法。
  • 如果您为每个页面加载生成散列或随机密钥,那么您将非常安全。充其量他们可以列出为当前页面生成的哈希/键,但这不会为他们提供有关您的实际数据结构的太多信息。
猜你喜欢
  • 2011-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多