Может ли параметр ValidateRequest страницы быть переопределен?

У меня есть форма ASP.NET MVC, которая может (обычно делает) отправить ответ, который вызвал бы ошибку "Обнаружено потенциально опасное значение Request.Form от клиента".

Чтобы попытаться обойти это, я поместил ValidateRequest="false" в директиву страницы.

Единственная проблема: я все еще получаю ошибку!

Теперь все было хорошо, пока я сегодня утром не обновил ASP.NET MVC RC и (согласно readme) не поместил в web-файл Views следующее:

<pages validateRequest="false" 
       pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
       pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
       userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
    <controls>
        <add assembly="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
    </controls>
</pages>

Итак, validateRequest должен быть ложным для всех страниц, верно? Что мне не хватает?

4 ответа

Решение

В MVC проверка выполняется на уровне контроллера, а не на уровне страницы. Чтобы понять, почему это так, представьте, что во время выполнения действия контроллера мы не знаем, какое представление будет выбрано для рендеринга. (Фактически, действие контроллера может вообще не отображать представление! Вместо этого оно может открыть запрос на загрузку файла на клиенте.) Кроме того, если пользователь отправляет вредоносные данные на сервер, к моменту отображения представления это слишком поздно что-либо предпринимать по этому поводу. Контроллер уже совершил опасный ввод в базу данных.

Вместо этого, пожалуйста, украсьте контроллер или действие атрибутом [ValidateInput(false)]. Это заставит нас отменить проверку запроса для этого контроллера или действия.

Необходимо украсить контроллер или действие атрибутом [ValidateInput(false)] и добавить requestValidationMode="2.0" в файл web.config: Пример:

Контроллер:

    [ValidateInput(false)]
    public class MensajesController : Controller
    {
        //or in an action
        [ValidateInput(false)]
        [HttpPost]
        public ActionResult Create(FormCollection collection)
        {
        }
    }

Файл конфигурации:

    <configuration>
        <system.web>
           <httpRuntime requestValidationMode="2.0"/>
        </system.web>
    </configuration>

У нас есть базовый контроллер, от которого наследуются наши контроллеры, что позволяет нам глобально отключить встроенную проверку ASP.NET-запросов:

    protected override void Initialize(RequestContext requestContext)
    {
        // no client input will be checked on any controllers
        ValidateRequest = false;
        base.Initialize(requestContext);
    }

Просто убедитесь, что вы проверяете все входные данные от клиента!

У меня была похожая проблема с использованием ASP.NET MVC 3 с.NET 4.0 и Windows Azure Access Control Service v2, где я мог получить ошибку:

System.Web.HttpRequestValidationException: A potentially dangerous Request.Form value was detected from the client (wresult="<t:RequestSecurityTo...").

и нашел лучшее решение, чем отключение проверки, - реализовать пользовательский RequestValidator, как описано в этой статье:

http://social.technet.microsoft.com/wiki/contents/articles/windows-identity-foundation-wif-a-potentially-dangerous-request-form-value-was-detected-from-the-client-wresult-quot-lt-t-requestsecurityto-quot.aspx

public class SampleRequestValidator : RequestValidator
{
    protected override bool IsValidRequestString( HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex )
    {
        validationFailureIndex = 0;
        if ( requestValidationSource == RequestValidationSource.Form && collectionKey.Equals( WSFederationConstants.Parameters.Result, StringComparison.Ordinal ) )
        {
            SignInResponseMessage message = WSFederationMessage.CreateFromFormPost( context.Request ) as SignInResponseMessage;
            if ( message != null )
            {
                return true;
            }
        }
        return base.IsValidRequestString( context, value, requestValidationSource, collectionKey, out validationFailureIndex );
    }
}

Единственная причина, по которой я смотрел дальше, чем отключение проверки, заключалась в том, что я видел, как это работало без отключения проверки, следуя этому руководству в учебном комплекте по платформе Windows Azure:

http://msdn.microsoft.com/en-us/WAZPlatformTrainingCourse_IntroToACSLabsV2

В любом случае, надеюсь, это кому-то пригодится и может обеспечить более детальный подход к решению этой проблемы в будущем. Следует отметить, что requestValidationMode="2.0" не требуется, если вы реализуете пользовательский RequestValidator.

Другие вопросы по тегам