使用 MVC5,我对特定的模型属性使用[AllowHtml]
,以允许将 HTML 发布到服务器。
在代码的某些地方,我想访问请求参数,如下所示:
string wlid = HttpContext.Current.Request.Params["wlid"];
但是,如果请求中包含任何 HTML,即使模型属性用[AllowHtml]
装饰,也会HttpRequestValidationException
失败。
有没有办法在不完全禁用请求验证的情况下访问HttpContext.Current.Request.Params["wlid"]
?
也许禁用请求验证,访问 Request.Params,然后立即再次启用它?
Request.Unvalidated
作为未经验证的等价物工作Request.Params
。
所以而不是
string wlid = HttpContext.Current.Request.Params["wlid"];
只需使用
string wlid = HttpContext.Current.Request.Unvalidated["wlid"];
或更好(如注释中建议的那样)以避免与静态成员耦合:
string wlid = this.HttpContext.Request.Unvalidated["wlid"];
TL;博士
如果您查看幕后情况,Request.Params
会合并以下数据(按此顺序):
- 查询字符串
- 形式
- 饼干
- 服务器变量
您可以在此处查看其源代码: https://github.com/microsoft/referencesource/blob/master/System.Web/HttpRequest.cs
关键部分是:
_params.Add(this.QueryString);
_params.Add(this.Form);
_params.Add(this.Cookies);
_params.Add(this.ServerVariables);
您是对的,访问Request.Params
会因HttpRequestValidationException
而失败,因为它会读取导致请求验证的底层集合。
文档:
当 ASP.NET 读取 HTTP 请求集合(如 Form、QueryString 和 Cookie 集合)中的值时,它会执行请求验证。在请求验证期间,ASP.NET 检查已发布的值并确定它们是否包含标记、脚本或保留字符。默认情况下,如果 ASP.NET 检测到任何这些类型的输入,则会引发 HttpRequestValidationException 异常。这有助于防止恶意脚本注入攻击您的网站。
所以这按设计工作。 如果要绕过 ASP.NET 请求验证,则有一个不同的对象。它被称为Request.Unvalidated
,包含查询字符串参数、表单变量和 cookie 的属性形式:
Request.Unvalidated.QueryString
Request.Unvalidated.Form
Request.Unvalidated.Cookies
读取这些属性不会触发请求验证,因此可以在您的案例中使用它们。 如果您不知道上述哪些属性包含您的数据,则可以以Request.Unvalidated["somekey"]
的形式使用该Request.Unvalidated
,因为它有一个索引器,可以从Form
、Cookies
、QueryString
或ServerVariables
集合中检索数据。所以这是一个非常接近(但未经验证Request.Params
!
请注意,绕过请求验证后,您将容易受到跨站点脚本的攻击,并且必须手动验证数据是否存在潜在的 XSS 攻击。
每当访问 Params 集合时都会触发验证。
我能够使用它来获得我们需要的价值
Request.Unvalidated.QueryString["key"]
注意:QueryString 与 Params 不完全相同,但对于我们的情况,我们需要的数据在查询字符串中,所以这有效。
有关详细信息,请参阅 MSDN for HttpRequestBase.Unvalidified。