asp.net-mvc ASP.NET MVC 使用自定义模型绑定器时从客户端检测到潜在危险的 Request.Form 值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17254354/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 02:57:43  来源:igfitidea点击:

ASP.NET MVC A potentially dangerous Request.Form value was detected from the client when using a custom modelbinder

asp.net-mvccustom-model-binder

提问by D-W

Getting the error here:

在这里得到错误:

ValueProviderResult value = bindingContext.ValueProvider.GetValue("ConfirmationMessage");

How do I allow on a selection of values only? i.e.

我如何只允许选择值?IE

[ValidateInput(false)]
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    ValueProviderResult value = bindingContext.ValueProvider.GetValue("ConfirmationMessage");
    ValueProviderResult value2 = bindingContext.ValueProvider.GetValue("ConfirmationMessage2");
}

回答by ericdc

You have a few options.

你有几个选择。

On the model add this attribute to each property that you need to allow HTML - best choice

在模型上将此属性添加到您需要允许 HTML 的每个属性 -最佳选择

using System.Web.Mvc;

[AllowHtml]
public string SomeProperty { get; set; }

On the controller action add this attribute to allow all HTML

在控制器操作上添加此属性以允许所有 HTML

[ValidateInput(false)]
public ActionResult SomeAction(MyViewModel myViewModel)

Brute force in web.config - definitely not recommended

在 web.config 中使用蛮力 -绝对不推荐

In the web.config file, within the tags, insert the httpRuntime element with the attribute requestValidationMode="2.0". Also add the validateRequest="false" attribute in the pages element.

在 web.config 文件的标记内,插入具有属性 requestValidationMode="2.0" 的 httpRuntime 元素。还要在 pages 元素中添加 validateRequest="false" 属性。

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

More info: http://davidhayden.com/blog/dave/archive/2011/01/16/AllowHtmlAttributeASPNETMVC3.aspx

更多信息:http: //davidhayden.com/blog/dave/archive/2011/01/16/AllowHtmlAttributeASPNETMVC3.aspx

The above works for usages of the default modelbinder.

以上适用于默认模型绑定器的用法。

Custom ModelBinder

自定义模型绑定器

It appears that a call to bindingContext.ValueProvider.GetValue() in the code above always validates the data, regardless any attributes. Digging into the ASP.NET MVC sources reveals that the DefaultModelBinder first checks if request validation is required and then calls the bindingContext.UnvalidatedValueProvider.GetValue() method with a parameter that indicates if validation is required or not.

似乎在上面的代码中调用 bindingContext.ValueProvider.GetValue() 总是会验证数据,而不管任何属性。深入研究 ASP.NET MVC 源代码会发现 DefaultModelBinder 首先检查是否需要验证请求,然后使用一个指示是否需要验证的参数调用 bindingContext.UnvalidatedValueProvider.GetValue() 方法。

Unfortunately we can't use any of the framework code because it's sealed, private or whatever to protect ignorant devs from doing dangerous stuff, but it's not too difficult to create a working custom model binder that respects the AllowHtml and ValidateInput attributes:

不幸的是,我们不能使用任何框架代码,因为它是密封的、私有的或任何保护无知的开发人员免于做危险事情的东西,但是创建一个尊重 AllowHtml 和 ValidateInput 属性的工作自定义模型绑定器并不难:

public class MyModelBinder: IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // First check if request validation is required
        var shouldPerformRequestValidation = controllerContext.Controller.ValidateRequest && bindingContext.ModelMetadata.RequestValidationEnabled;

        // Get value
        var valueProviderResult = bindingContext.GetValueFromValueProvider(shouldPerformRequestValidation);
        if (valueProviderResult != null)
        {
            var theValue = valueProviderResult.AttemptedValue;

            // etc...
        }
    }
}

The other required piece is a way to retrieve an unvalidated value. In this example we use an extension method for the ModelBindingContext class:

另一个必需的部分是一种检索未验证值的方法。在这个例子中,我们使用 ModelBindingContext 类的扩展方法:

public static class ExtensionHelpers
{
    public static ValueProviderResult GetValueFromValueProvider(this ModelBindingContext bindingContext, bool performRequestValidation)
    {
        var unvalidatedValueProvider = bindingContext.ValueProvider as IUnvalidatedValueProvider;
        return (unvalidatedValueProvider != null)
          ? unvalidatedValueProvider.GetValue(bindingContext.ModelName, !performRequestValidation)
          : bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
    }
}

More info on this at http://blogs.taiga.nl/martijn/2011/09/29/custom-model-binders-and-request-validation/

有关更多信息,请访问http://blogs.taiga.nl/martijn/2011/09/29/custom-model-binders-and-request-validation/

回答by D-W

Try:

尝试:

HttpRequestBase request = controllerContext.HttpContext.Request;
string re = request.Unvalidated.Form.Get("ConfirmationMessage")

回答by Mike Godin

Expanding upon the answer from @D-W, in my Edit controller, in iterating over form values, I had to replace all instances of Request.Params.AllKeyswith Request.Unvalidated.Form.AllKeysand all instances of Request[key]with Request.Unvalidated.Form[key].

扩展来自@DW 的答案,在我的 Edit 控制器中,在迭代表单值时,我必须替换Request.Params.AllKeyswith 的Request.Unvalidated.Form.AllKeys所有实例和Request[key]with 的所有实例Request.Unvalidated.Form[key]

This was the only solution that worked for me.

这是唯一对我有用的解决方案。

回答by Ryozzo

As Mike Godin wrote, even if you set [ValidateInput(false)] attribute, you have to use Request.Unvalidated.Forminstead of Request.FormThis worked for me with ASP.NET MVC 5

正如 Mike Godin 所写,即使您设置了 [ValidateInput(false)] 属性,您也必须使用Request.Unvalidated.Form而不是Request.Form这对我使用 ASP.NET MVC 5

回答by Prakash Rajendran

Here are the steps to encode at client level and decode it at server level:

以下是在客户端级别进行编码并在服务器级别进行解码的步骤:

  1. Post the form using jquery submit method.

  2. In jquery button click event method encode field that you want to post to server. Example:

    $("#field").val(encodeURIComponent($("#field").val()))
    $("#formid").submit();
    
  3. In Controller Level access all form id value using

    HttpUtility.UrlDecode(Request["fieldid"])
    
  1. 使用 jquery submit 方法发布表单。

  2. 在 jquery 按钮单击事件方法编码要发布到服务器的字段。例子:

    $("#field").val(encodeURIComponent($("#field").val()))
    $("#formid").submit();
    
  3. 在控制器级别访问所有表单 id 值使用

    HttpUtility.UrlDecode(Request["fieldid"])
    

Sample example:

示例:

  • Controller level:

    public ActionResult Name(string id)
    {
    
        CheckDispose();
        string start = Request["start-date"];
        string end = Request["end-date"];
        return View("Index", GetACPViewModel(HttpUtility.UrlDecode(Request["searchid"]), start, end));
    }
    
  • Client level:

    <% using (Html.BeginForm("Name", "App", FormMethod.Post, new { id = "search-form" }))
    { %>
    <div>
    <label  for="search-text" style="vertical-align: middle" id="search-label" title="Search for an application by name, the name for who a request was made, or a BEMSID">App, (For Who) Name, or BEMSID: </label>
    <%= Html.TextBox("searchid", null, new {value=searchText, id = "search-text", placeholder = "Enter Application, Name, or BEMSID" })%>
    </div>
    <div>
    <input id="start-date" name="start-date" class="datepicker" type="text"  placeholder="Ex: 1/1/2012"/>
    </div>
    <div>
    <input id="end-date" name="end-date" class="datepicker" type="text"  placeholder="Ex: 12/31/2012"/>
    </div>
    <div>
    <input type="button" name="search" id="btnsearch" value="Search" class="searchbtn" style="height:35px"/>
    </div> 
    <% } %>
    
  • 控制器级别:

    public ActionResult Name(string id)
    {
    
        CheckDispose();
        string start = Request["start-date"];
        string end = Request["end-date"];
        return View("Index", GetACPViewModel(HttpUtility.UrlDecode(Request["searchid"]), start, end));
    }
    
  • 客户端级别:

    <% using (Html.BeginForm("Name", "App", FormMethod.Post, new { id = "search-form" }))
    { %>
    <div>
    <label  for="search-text" style="vertical-align: middle" id="search-label" title="Search for an application by name, the name for who a request was made, or a BEMSID">App, (For Who) Name, or BEMSID: </label>
    <%= Html.TextBox("searchid", null, new {value=searchText, id = "search-text", placeholder = "Enter Application, Name, or BEMSID" })%>
    </div>
    <div>
    <input id="start-date" name="start-date" class="datepicker" type="text"  placeholder="Ex: 1/1/2012"/>
    </div>
    <div>
    <input id="end-date" name="end-date" class="datepicker" type="text"  placeholder="Ex: 12/31/2012"/>
    </div>
    <div>
    <input type="button" name="search" id="btnsearch" value="Search" class="searchbtn" style="height:35px"/>
    </div> 
    <% } %>
    

In Document Ready function:

在文档就绪功能中:

$(function () {     
  $("#btnsearch").click(function () {  
    $("#search-text").val(encodeURIComponent($("#search-text").val()));
    $("#search-form").submit();
  });
});