禁用 HttpContext.Current.Request.Params 的请求验证



使用 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,因为它有一个索引器,可以从FormCookiesQueryStringServerVariables集合中检索数据。所以这是一个非常接近(但未经验证Request.Params

请注意,绕过请求验证后,您将容易受到跨站点脚本的攻击,并且必须手动验证数据是否存在潜在的 XSS 攻击。

每当访问 Params 集合时都会触发验证。

我能够使用它来获得我们需要的价值

Request.Unvalidated.QueryString["key"]

注意:QueryString 与 Params 不完全相同,但对于我们的情况,我们需要的数据在查询字符串中,所以这有效。

有关详细信息,请参阅 MSDN for HttpRequestBase.Unvalidified。

最新更新