如何处理“从客户端检测到潜在危险的Request.Form值”?

mar*_*zzz 5 asp.net-mvc exception .net-4.6.1

我在 ASP.NET MVC Framework 应用程序的处理程序中收到了一些“一般”错误protected void Application_Error()。异常消息是:

\n
\n

从客户端检测到潜在危险的 Request.Form 值

\n
\n

有很多方法可以触发此操作;仅一个例子是拨打电话,例如

\n
http:/www.mywebsite.com/http:/www.mywebsite.com/\n
Run Code Online (Sandbox Code Playgroud)\n

我想仅为这种异常创建一个“过滤器”,并相应地重定向或管理请求。我不想禁用它,只是想管理它。我也不希望它落入通用protected void Application_Error()处理程序\xe2\x80\x94 中,或者至少,我想在该方法内部管理它,这样它就不会被我的日志记录等处理。

\n

我该如何处理这个问题?

\n

Jer*_*ney 3

听起来您已经Application_Error()配置了一个事件处理程序,但不希望您的标准日志记录包含此类错误,大概是因为它使您的日志变得混乱,其中包含您不打算调查的异常更远。

\n

背景

\n

该错误应该HttpRequestValidationException. 如果这里是这种情况,当然,这将是一个微不足道的问题。然而,根据您提供的测试用例,您实际上得到了更一般的HttpException.

\n

正如您在评论中指出的,这是由于 .NET Framework在请求管道的早期RequestValidator(即评估之前)执行了 URL 中的字符验证。这可能是为什么HttpRequestValidationException不会被抛出的一个因素,否则如果该方法返回,就会发生RequestValidator这种IsValidRequestString()情况false

\n

解决方法

\n

不幸的是,由于该类HttpException用于处理各种各样的错误,因此很难处理。幸运的是,正如您还发现的那样RequestValidator,您可以通过禁用requestPathInvalidCharactersweb.config配置自定义来将此验证推送到RequestValidator

\n
<configuration>\n  <system.web>\n    <compilation targetFramework="4.6.1" />\n    <httpRuntime \n      targetFramework="4.6.1" \n      requestValidationType="CustomRequestValidator" \n      requestPathInvalidCharacters="" \n    />\n  </system.web>\n</configuration>\n
Run Code Online (Sandbox Code Playgroud)\n
\n

注意:假设它requestValidationType不在项目的根命名空间中,则需要以其命名空间为前缀。

\n
\n

requestPathInvalidCharacters的默认值为<,>,*,%,&,:,\\,?,因此您现在需要在您的 中重现该验证CustomRequestValidator

\n
public class CustomRequestValidator : RequestValidator\n{\n    private static readonly char[] requestPathInvalidCharacters = new [] { \'<\', \'>\', \'*\', \'%\', \'&\', \':\', \'\\\\\' };\n    protected override bool IsValidRequestString(\n        HttpContext context, \n        string value, \n        RequestValidationSource requestValidationSource, \n        string collectionKey, \n        out int validationFailureIndex\n    ) {\n        if (requestValidationSource is RequestValidationSource.PathInfo || requestValidationSource is RequestValidationSource.Path) {\n            var errorIndex = value.IndexOfAny(requestPathInvalidCharacters);\n            if (errorIndex >= 0) {\n                validationFailureIndex = errorIndex;\n                return false;\n            }\n        }\n        return base.IsValidRequestString(\n            context, \n            value, \n            requestValidationSource, \n            collectionKey, \n            out validationFailureIndex\n        );\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这首先重新创建路径的验证(由参数表示),然后从基础value执行标准的开箱即用处理。现在这将抛出预期的.IsValidRequestString()RequestValidatorHttpRequestValidationException

\n

管理异常

\n

此时,如上所述,这已成为一个微不足道的问题。由于RequestValidator在解析 MVC 路由之前对其进行评估,因此您仍然无法在此处使用全局异常过滤器。但是,由于您已经有了一个Application_Error()事件处理程序设置,因此您可以global.asax.cs使用以下命令来管理它:

\n
void Application_Error(object sender, EventArgs e)\n{\n\n    Exception ex = Server.GetLastError();\n\n    if (ex is HttpRequestValidationException)\n    {\n        Response.Clear();\n        Response.StatusCode = 200;\n        // Manage request as you deem appropriate; e.g.,\n        Response.Redirect("~/Errors/RequestValidation/");\n        Response.End();\n        return;\n    }\n\n    // Your current logging logic\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

额外细节

\n

几乎每个 ASP.NET 请求\xe2\x80\x94都会至少RequestValidator调用两次 ,一次针对( 通常为空) ,一次针对(请参阅)。绑定到路由的每个、、、或 文件也将被验证。pathinfopathrequestValidationSourceQueryStringFormCookieHeader

\n

Microsoft 试图限制需要验证的请求。例如,他们不检查对静态文件的请求。此外,未绑定到路由的参数将被跳过。由于潜在危险的字符不能在路由参数键中使用,因此我们不需要担心验证这些字符。

\n

此外,正如您所指出的,也不需要验证无效路径字符的参数(例如 cookie 值)。集合值仍将由基本逻辑评估是否存在其他潜在危险字符串\xe2\x80\x94,例如\xe2\x80\x94 。<scriptIsValidRequestString()

\n