C# 将参数从视图传递到控制器并作为视图返回的安全方法
我正在为querystring寻找一种安全的替代方法,我将把一个参数传递给同一控制器上的控制器方法,并将其作为视图返回 类别视图:C# 将参数从视图传递到控制器并作为视图返回的安全方法,c#,asp.net-mvc,parameter-passing,C#,Asp.net Mvc,Parameter Passing,我正在为querystring寻找一种安全的替代方法,我将把一个参数传递给同一控制器上的控制器方法,并将其作为视图返回 类别视图: @foreach (Project.Framework.ModelClasses.productCategories productCategories in ViewBag.Categories) { @Html.ActionLink(productCategories.description, "Products",
@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();
}
公共ActionResult产品(字符串类别ID、字符串关键字、字符串描述)
{
ViewBag.appPath=ConfigurationManager.AppSettings[“appPath”].ToString();
方法=新方法();
Methods.tokenHeader=(字符串)会话[“token”];
Methods.cookieContainer=(cookieContainer)会话[“cookies”];
响应shopnowProductsResponse=Methods.shopnowProductsGet(categoryID,关键字);
if(shopnowProductsResponse.Code==“000”)
{
列表产品=新列表();
产品=(列表)shopnowProductsResponse.Data;
字符串FPRFlag=“0”;
foreach(产品中的产品)
{
如果(FPRFlag!=“1”)
{
如果(product.FPRFlag==“1”)
{
FPRFlag=product.FPRFlag;
}
}
其他的
{
后藤下州;
}
}
下一州:
ViewBag.FPRFlag=FPRFlag;
ViewBag.Description=说明;
ViewBag.Products=产品;
}
返回视图();
}
注意:关键字是可选的假设您只想以最终用户无法从URL中获取所有产品数据的方式对这些链接进行编码,您可以通过在链接中使用替代代码来实现这一点。我会使用散列值:
@foreach (Project.Framework.ModelClasses.productCategories category in ViewBag.Categories)
{
@Html.ActionLink(category.description, "Products", "Shop",
new {
hc = category.categoryID.GetHashCode()
})
}
然后在控制器上查找哈希代码,而不是类别ID
这仍然存在两个问题:
类别ID
,并将结果存储在会话
存储中,然后重定向到产品
页面:
public ActionResult SetCategory(int hc)
{
string catID = HashToCategoryID(hc);
Session["categoryID"] = catID;
return RedirectToAction("Products");
}
这不仅会将用户的浏览器放回产品
页面,而且(在大多数情况下)还会确保设置类别
URL甚至不会显示在浏览器历史记录中。一般来说,浏览器历史记录甚至不会显示它首先从产品
页面导航出去,因此点击后退
按钮将把它们从页面带到它们第一次进入之前所在的位置
另一个问题-哈希代码不改变-可以通过两种方式解决:使用一个在每次访问时都会改变的值(如会话ID)来添加哈希值,或者生成随机值并将其存储在会话
存储器中进行查找
例如:
// 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] })
}
@{//从ViewBag中获取hashcode字典
Dictionary hashcodes=ViewBag[“CategoryToHash”]作为字典;
}
@foreach(ViewBag.Categories中的Project.Framework.ModelClasses.productCategories类别)
{
@ActionLink(product.description,“SetCategory”,新的{hc=hashcodes[product.categoryID]})
}
实际上,您现在有一个过期的一次性代码列表,每次用户重新访问产品
页面时,这些代码都会被替换为新代码。让同一代码在同一类别中多次运行的几率是微乎其微的,除非在同一会话中单击链接,否则链接将失败
说到失败。。。您需要在其中添加一系列错误处理。您在问题中使用的“安全”是什么意思?(也许数据签名可以解决这个问题?)?通过将其作为路由的一部分?出于安全原因,我无法通过URL传递任何参数,因为我正在传递敏感数据。请定义“安全”。您需要对用户隐藏它吗?对监视交通的人隐瞒?您是否需要能够进行完整性检查?”“安全”意味着很多事情。如果它是敏感数据,那么您应该将其保存在服务器端并将其置于会话中。根据定义,发送到客户端(浏览器)的任何内容都是不安全的。您当然可以对其进行加密,但既然可以将其保存在服务器端,为什么还要经历所有这些麻烦呢。这就是我在项目中所做的,但没有使用哈希。谢谢你的回答。现在我在想,浏览器中的用户是否有可能进入这个方法。如果你为每个页面加载生成哈希或随机键,那么你就相当安全了。他们最多只能列出为当前页面生成的哈希值/键,但这不会给他们提供关于实际数据结构的太多信息。