ASP.NET MVC Một giá trị Request.Form có thể nguy hiểm đã được phát hiện từ máy khách khi sử dụng một trình mô hình tùy chỉnh


95

Bắt lỗi ở đây:

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

Làm cách nào để chỉ cho phép lựa chọn các giá trị? I E

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

1
Có thể có bản sao của một giá trị Request.Form tiềm ẩn nguy hiểm đã được phát hiện từ máy khách , không thành vấn đề nếu đó là Biểu mẫu web hay MVC.
Erik Philips

2
Cảm ơn, nhưng bạn havent nhìn vấn đề của tôi là khác nhau của nó
DW

Cùng một vấn đề gốc chính xác, sự khác biệt duy nhất là có thể có những cách cụ thể MVC để giải quyết nó.
Erik Philips

Khi sử dụng EF, hãy xem câu trả lời bizzehdee tại đây stackoverflow.com/questions/17964313/…
Petr

Câu trả lời:


223

Bạn có một vài lựa chọn.

Trên mô hình, hãy thêm thuộc tính này vào từng thuộc tính mà bạn cần để cho phép HTML - lựa chọn tốt nhất

using System.Web.Mvc;

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

Trên hành động của bộ điều khiển, hãy thêm thuộc tính này để cho phép tất cả HTML

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

Brute force trong web.config - chắc chắn không được khuyến khích

Trong tệp web.config, bên trong các thẻ, hãy chèn phần tử httpRuntime với thuộc tính requestValidationMode = "2.0". Cũng thêm thuộc tính validateRequest = "false" trong phần tử trang.

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

Thông tin thêm: http://davidhayden.com/blog/dave/archive/2011/01/16/AllowHtmlAttributeASPNETMVC3.aspx

Phần trên phù hợp với cách sử dụng của trình mô hình mặc định.

Mô hình tùy chỉnh

Có vẻ như lời gọi đến bindContext.ValueProvider.GetValue () trong đoạn mã trên luôn xác thực dữ liệu, bất kể thuộc tính nào. Tìm hiểu kỹ các nguồn ASP.NET MVC cho thấy rằng trước tiên, DefaultModelBinder sẽ kiểm tra xem có cần xác thực yêu cầu hay không và sau đó gọi phương thức bindContext.UnvalidatedValueProvider.GetValue () với một tham số cho biết có cần xác thực hay không.

Thật không may, chúng tôi không thể sử dụng bất kỳ mã khung nào vì nó được niêm phong, riêng tư hoặc bất cứ thứ gì để bảo vệ những nhà phát triển thiếu hiểu biết khỏi làm những điều nguy hiểm, nhưng không quá khó để tạo một chất kết dính mô hình tùy chỉnh hoạt động tôn trọng các thuộc tính AllowHtml và 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...
        }
    }
}

Phần bắt buộc khác là một cách để truy xuất một giá trị chưa được xác thực. Trong ví dụ này, chúng tôi sử dụng một phương thức mở rộng cho lớp 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);
    }
}

Thông tin thêm về điều này tại http://blogs.taiga.nl/martijn/2011/09/29/custom-model-binders-and-request-validation/


tôi có điều này trên bộ điều khiển [HttpPost, ValidateInput (false)] và tôi vẫn nhận được lỗi
DW

Xem câu trả lời sửa đổi của tôi với một khoảng cách này khi sử dụng một tùy chỉnh ModelBinder
ericdc

Cảm ơn, nhưng nó không thích dòng này bindingContext.GetValueFromValueProvider
DW.

GetValueFromValueProvider cần phải ở trong một lớp tĩnh công khai. Kiểm tra các chỉnh sửa ở trên.
ericdc

Ta, valueProviderResult reutrns null tho? var valueProviderResult = bindingContext.GetValueFromValueProvider (shouldPerformRequestValidation);
DW

30

Thử:

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

Khi tôi thử điều này, tôi nhận được một ngoại lệ cho biết: Không thể sử dụng thành viên không thể lập hóa đơn 'System.web.HttpRequestBase.Unvalidated' như một phương thức. Điều này đã thay đổi?
Stack0verflow

7
Dòng thứ hai thực sự phải làvar re = request.Unvalidated.Form["ConfirmationMessage"];
Stack0verflow

4

Mở rộng dựa trên câu trả lời từ @DW, trong bộ điều khiển Chỉnh sửa của tôi, khi lặp lại các giá trị biểu mẫu, tôi phải thay thế tất cả các bản sao của Request.Params.AllKeyswith Request.Unvalidated.Form.AllKeysvà tất cả các bản sao của Request[key]with Request.Unvalidated.Form[key].

Đây là giải pháp duy nhất phù hợp với tôi.


0

Như Mike Godin đã viết, ngay cả khi bạn đặt thuộc tính [ValidateInput (false)], bạn phải sử dụng Request.Unvalidated.Form thay vì Request.Form Điều này làm việc với tôi với ASP.NET MVC 5


1
Đây thực sự là một lời khuyên hữu ích, khi truy cập dữ liệu từ bộ điều khiển cơ sở (tức là cho mục đích ghi nhật ký hoặc gỡ lỗi) bất kỳ quyền truy cập nào vào Request.Form sẽ ném ra ngoại lệ ngay cả khi mô hình có thuộc tính này.
nsimeonov

-5

Dưới đây là các bước để mã hóa ở cấp máy khách và giải mã ở cấp máy chủ:

  1. Đăng biểu mẫu bằng phương pháp gửi jquery.

  2. Trong nút jquery bấm vào trường mã hóa phương pháp sự kiện mà bạn muốn đăng lên máy chủ. Thí dụ:

    $("#field").val(encodeURIComponent($("#field").val()))
    $("#formid").submit();
  3. Trong Cấp bộ điều khiển, truy cập tất cả giá trị id biểu mẫu bằng

    HttpUtility.UrlDecode(Request["fieldid"])

Ví dụ mẫu:

  • Cấp điều khiển:

    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));
    }
  • Cấp độ khách hàng:

    <% 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> 
    <% } %>

Trong chức năng Sẵn sàng Tài liệu:

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

4
Jquery và công nghệ phía máy khách không liên quan gì đến MVC, việc xác thực xảy ra ở phía máy chủ với khuôn khổ MVC. Đó không phải là một câu trả lời hợp lệ
diegosasw

1
Cho rằng Microsoft thực sự bỏ qua thuộc tính AllowHtml và cho rằng giải pháp khả thi duy nhất ở phía máy chủ là thay thế chức năng của chất kết dính mô hình mặc định, tôi cho rằng mã hóa phía máy khách là một tùy chọn hoàn toàn hợp lệ.
Jonathan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.