问题 如何在ASP.NET WebAPI中覆盖RequestValidation


我遇到了包含“危险字符”作为Web API URL一部分的请求的问题。 Url包含一个正确的Url编码,但仍会导致请求验证ASP.NET错误。

与MVC不同,似乎没有[ValidateInput(false)]属性来强制和禁用此功能。


6777
2018-03-14 08:28


起源



答案:


原来答案是在web.config中使用以下方法执行此操作:

<system.web>
  <httpRuntime requestPathInvalidCharacters="" />  
</system.web>

您可以在全局或子目录级别设置此项。你可以利用 <location path=""> 元素仅在某些路径下指定此设置。例如,如果受影响的Web API路由存在于下方 API /图片 你可以做以下事情:

<location path="api/images">
  <system.web>
    <httpRuntime requestPathInvalidCharacters="" />  
  </system.web>
</location>

更多信息: https://msdn.microsoft.com/en-us/library/e1f13641(v=vs.100).aspx


8
2018-03-14 08:49



这是唯一对我有用的解决方案。添加 requestValidationMode='2.0' 到web.config并尝试 [ValidateInput(false)] 动作方法的属性不起作用。我添加后它开始工作了 requestPathInvalidCharacters=""。我认为这是因为这里的错误是Request.Path验证的一部分,而不是Request.Form验证。 - quakkels
它不需要是全局的,只需使用即可 location 限制路径的元素。因此,如果您的Web API路由不足 api/foo 你可以限制位置 path="api/foo" 并添加 httpRuntime 在那里配置。确认这在IIS中运行良好。 MSDN也明确表示 <httpRuntime>可以“在机器,站点,应用程序和子目录级别声明”。我更新了答案。 - kamranicus


答案:


原来答案是在web.config中使用以下方法执行此操作:

<system.web>
  <httpRuntime requestPathInvalidCharacters="" />  
</system.web>

您可以在全局或子目录级别设置此项。你可以利用 <location path=""> 元素仅在某些路径下指定此设置。例如,如果受影响的Web API路由存在于下方 API /图片 你可以做以下事情:

<location path="api/images">
  <system.web>
    <httpRuntime requestPathInvalidCharacters="" />  
  </system.web>
</location>

更多信息: https://msdn.microsoft.com/en-us/library/e1f13641(v=vs.100).aspx


8
2018-03-14 08:49



这是唯一对我有用的解决方案。添加 requestValidationMode='2.0' 到web.config并尝试 [ValidateInput(false)] 动作方法的属性不起作用。我添加后它开始工作了 requestPathInvalidCharacters=""。我认为这是因为这里的错误是Request.Path验证的一部分,而不是Request.Form验证。 - quakkels
它不需要是全局的,只需使用即可 location 限制路径的元素。因此,如果您的Web API路由不足 api/foo 你可以限制位置 path="api/foo" 并添加 httpRuntime 在那里配置。确认这在IIS中运行良好。 MSDN也明确表示 <httpRuntime>可以“在机器,站点,应用程序和子目录级别声明”。我更新了答案。 - kamranicus


如果在配置中将RequestValidation设置为4.0,则答案为否。但是,您可以恢复为2.0请求验证,在这种情况下,MVC属性可以按预期工作:默认情况下验证并在需要时显式覆盖。

<httpRuntime executionTimeout="300" requestValidationMode="2.0" />

在这里详细讨论了这个和一些选项: http://www.west-wind.com/weblog/posts/2010/Aug/19/RequestValidation-Changes-in-ASPNET-40


2
2018-04-10 00:54



这是唯一对我有用的选项。 - santos


通过设置,您可以对此进行更精细的控制 requestValidationType 的属性 httpRuntime 元素到继承自定义的类型 System.Web.Util.RequestValidator 并覆盖 IsValidRequestString

不幸的是,这不是WebAPI管道的一部分,因此无法直接检查诸如动作过滤器之类的内容(即控制器方法上的属性)。

但是,如果您特别关注“表单验证”字段,则在访问它们之前不会调用验证程序,这会在触发“操作过滤器”之后发生,因此您可以通过创建类来禁用使用属性的验证下列...

public class AllowFormHtmlAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        HttpContext.Current.Items["AllowFormHtml"] = true;
    }
}

public class CustomRequestValidator : RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        if (context.Items["AllowFormHtml"] as bool? == true && requestValidationSource == RequestValidationSource.Form)
        {
            validationFailureIndex = 0;
            return true;
        }

        return base.IsValidRequestString(
            context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }
}

...然后只是用你的控制器方法注释 [AllowFormHtml]

但是,如果您直接从HttpRequest访问表单字段,则使用起来更简单 HttpRequest.Unvalidated,绕过验证。


2
2017-07-22 14:29





@Levi 我们的网络安全人员:

配置是唯一的方法。甚至是MVC的 [ValidateInput(假)]对这种特殊情况无济于事。

禁用它 Web.config文件 没有必要是一个可怕的想法。如果您通过验证和编码不受信任的数据来遵循良好的安全实践,那么在应用程序范围内应用它是完全正确的。


1
2018-04-10 00:41



[ValidateInput(false)] 在我的情况下不起作用。我想是因为 [ValidateInput(false)] 是指 Request.Form 而不是 Request.Path。 - quakkels