将参数从视图传递到控制器并将其作为视图返回的安全方法

时间:2014-06-26 22:49:30

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

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

分类视图:

@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();
    }

注意:关键字是可选的

1 个答案:

答案 0 :(得分: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. 每次哈希码列表都相同。
  3. 可以使用中间操作修复第一个操作,该操作将哈希代码转换回categoryID并将结果存储在Session存储中,然后重定向到Products页面:

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

    这不仅会将用户的浏览器返回到Products页面,还会确保(在大多数情况下)SetCategory URL甚至不会显示在浏览器历史记录中。通常情况下,浏览器历史记录甚至不会显示它首先离开Products页面,因此点击Back按钮会将它们从页面移到最初到达之前的任何位置英寸

    另一个问题 - 哈希代码没有改变 - 可以通过以下两种方式修复:使用将从访问更改为访问的值(如会话ID)更新哈希,或者生成随机值并将其存储在{{存储用于查找。

    例如:

    Session

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

    // 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] }) } 页面时,该代码将过期并替换为新代码。对于同一类别,获得相同代码多次工作的几率是无穷小的,除非从同一会话中单击链接,否则它将失败。

    说到失败......你需要在那里添加一堆错误处理。