Как переопределить RequestValidation в ASP.NET WebAPI

У меня возникают проблемы с запросами, которые содержат «опасные символы» как часть URL-адреса веб-API. URL-адрес включает &, который правильно закодирован в URL-адресе, но все же вызывает ошибку проверки запроса ASP.NET.

В отличие от MVC, похоже, нет атрибута [ValidateInput(false)] для принудительного отключения этой функции.


person Rick Strahl    schedule 14.03.2012    source источник


Ответы (4)


Оказывается, ответ заключается в том, чтобы сделать это в web.config, используя:

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

Вы можете установить это глобально или на уровне подкаталога. Вы можете использовать элемент <location path="">, чтобы указать этот параметр только под определенными путями. Например, если ваш затронутый маршрут веб-API находится под api/images, вы можете сделать следующее:

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

Дополнительные сведения: https://msdn.microsoft.com/en-us/library/e1f13641(v=vs.100).aspx

person Rick Strahl    schedule 14.03.2012
comment
Это единственное решение, которое сработало для меня. Добавление requestValidationMode='2.0' в web.config и использование атрибута [ValidateInput(false)] в методе действия НЕ сработало. Он начал работать после того, как я добавил requestPathInvalidCharacters="". Я думаю, это потому, что ошибка здесь является частью проверки Request.Path, а не проверки Request.Form. - person quakkels; 06.08.2013
comment
Он не должен быть глобальным, просто используйте элемент location для ограничения пути. Поэтому, если ваш маршрут веб-API находится под api/foo, вы можете ограничить местоположение до path="api/foo" и добавить туда конфигурацию httpRuntime. Подтверждено, что это отлично работает в IIS. Также MSDN явно указывает, что <httpRuntime> может быть объявлено на уровне компьютера, сайта, приложения и подкаталога. Я обновил ответ. - person kamranicus; 31.07.2016

Если в конфигурации 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

person Rick Strahl    schedule 10.04.2013

за @Levi нашего специалиста по веб-безопасности:

Конфиг - единственный способ сделать это. Даже [ValidateInput(false)] не поможет в этом конкретном случае.

Отключение его в Web.config не обязательно является ужасной идеей. Если вы следуете хорошей практике безопасности, проверяя и кодируя ненадежные данные, вполне нормально применять ее для всего приложения.

person RickAndMSFT    schedule 10.04.2013
comment
[ValidateInput(false)] в моем случае не работает. Я думаю, это потому, что [ValidateInput(false)] относится к Request.Form, а не к Request.Path. - person quakkels; 06.08.2013

Вы можете получить более тонкий контроль над этим, установив для атрибута 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, который обходит проверку.

person hgcummings    schedule 22.07.2015