ASP.NET MVC Nilai Request.Form yang berpotensi berbahaya terdeteksi dari klien saat menggunakan modelbinder kustom

95

Mendapatkan kesalahan di sini:

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

Bagaimana cara mengizinkan pilihan nilai saja? yaitu

[ValidateInput(false)]
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    ValueProviderResult value = bindingContext.ValueProvider.GetValue("ConfirmationMessage");
    ValueProviderResult value2 = bindingContext.ValueProvider.GetValue("ConfirmationMessage2");
}
DW
sumber
1
Kemungkinan duplikat dari nilai Request.Form yang berpotensi berbahaya terdeteksi dari klien , tidak peduli apakah itu Webforms atau MVC.
Erik Philips
2
Terima kasih, tetapi Anda belum menganggap masalah saya berbeda
DW
Masalah akar yang sama persis, satu-satunya perbedaan adalah mungkin ada cara khusus MVC untuk mengatasinya.
Erik Philips
Saat menggunakan EF, lihat jawaban bizzehdee di sini stackoverflow.com/questions/17964313/…
Petr

Jawaban:

223

Anda punya beberapa pilihan.

Pada model, tambahkan atribut ini ke setiap properti yang Anda perlukan untuk mengizinkan HTML - pilihan terbaik

using System.Web.Mvc;

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

Pada tindakan pengontrol, tambahkan atribut ini untuk mengizinkan semua HTML

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

Brute force di web.config - sangat tidak direkomendasikan

Di file web.config, di dalam tag, masukkan elemen httpRuntime dengan atribut requestValidationMode = "2.0". Tambahkan juga atribut validateRequest = "false" di elemen halaman.

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

Info lebih lanjut: http://davidhayden.com/blog/dave/archive/2011/01/16/AllowHtmlAttributeASPNETMVC3.aspx

Di atas bekerja untuk penggunaan modelbinder default.

ModelBinder Kustom

Tampaknya panggilan ke bindingContext.ValueProvider.GetValue () dalam kode di atas selalu memvalidasi data, apa pun atributnya. Menggali ke dalam sumber ASP.NET MVC mengungkapkan bahwa DefaultModelBinder pertama memeriksa apakah validasi permintaan diperlukan dan kemudian memanggil metode bindingContext.UnvalidatedValueProvider.GetValue () dengan parameter yang menunjukkan apakah validasi diperlukan atau tidak.

Sayangnya kami tidak dapat menggunakan kode kerangka kerja apa pun karena tersegel, pribadi, atau apa pun untuk melindungi pengembang yang tidak tahu dari melakukan hal-hal berbahaya, tetapi tidak terlalu sulit untuk membuat pengikat model khusus yang berfungsi yang menghormati atribut AllowHtml dan 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...
        }
    }
}

Bagian lain yang diperlukan adalah cara untuk mengambil nilai yang tidak divalidasi. Dalam contoh ini kami menggunakan metode ekstensi untuk kelas 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);
    }
}

Info lebih lanjut tentang ini di http://blogs.taiga.nl/martijn/2011/09/29/custom-model-binders-and-request-validation/

ericdc
sumber
saya memiliki ini di pengontrol [HttpPost, ValidateInput (false)] dan saya masih mendapatkan kesalahan
DW
Lihat jawaban saya yang direvisi dengan cara menyiasatinya saat menggunakan
pengikat
Terima kasih, tetapi tidak suka baris ini bindingContext.GetValueFromValueProvider
DW
GetValueFromValueProvider harus berada dalam kelas statis publik. Lihat pengeditan di atas.
ericdc
Ta, valueProviderResult reutrns null tho? var valueProviderResult = bindingContext.GetValueFromValueProvider (shouldPerformRequestValidation);
DW
31

Mencoba:

HttpRequestBase request = controllerContext.HttpContext.Request;
string re = request.Unvalidated.Form.Get("ConfirmationMessage")
DW
sumber
Ketika saya mencoba ini, saya mendapatkan pengecualian yang mengatakan: Anggota tidak dapat dipanggil 'System.web.HttpRequestBase.Unvalidated' tidak dapat digunakan seperti metode. Apakah hal ini berubah?
Stack0verflow
7
Baris kedua harus benar-benarvar re = request.Unvalidated.Form["ConfirmationMessage"];
Stack0verflow
5

Memperluas jawaban dari @DW, di pengontrol Edit saya, dalam mengulang nilai formulir, saya harus mengganti semua contoh Request.Params.AllKeysdengan Request.Unvalidated.Form.AllKeysdan semua contoh Request[key]dengan Request.Unvalidated.Form[key].

Ini adalah satu-satunya solusi yang berhasil untuk saya.

Mike Godin
sumber
0

Seperti yang ditulis Mike Godin, meskipun Anda menyetel atribut [ValidateInput (false)], Anda harus menggunakan Request.Unvalidated.Form alih-alih Request.Form. Ini berfungsi untuk saya dengan ASP.NET MVC 5

Ryozzo
sumber
1
Ini sebenarnya adalah saran yang berguna, karena mengakses data dari pengontrol dasar (yaitu untuk tujuan log atau debug) akses apa pun ke Request.Form melempar pengecualian meskipun model memiliki atribut ini.
nsimeonov
-5

Berikut langkah-langkah untuk menyandikan di tingkat klien dan mendekodekannya di tingkat server:

  1. Posting formulir menggunakan metode submit jquery.

  2. Di jquery klik tombol event method encode field yang ingin Anda posting ke server. Contoh:

    $("#field").val(encodeURIComponent($("#field").val()))
    $("#formid").submit();
    
  3. Di Tingkat Pengontrol, akses semua nilai id formulir menggunakan

    HttpUtility.UrlDecode(Request["fieldid"])

Contoh contoh:

  • Tingkat pengontrol:

    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));
    }
    
  • Tingkat klien:

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

Dalam fungsi Document Ready:

$(function () {     
  $("#btnsearch").click(function () {  
    $("#search-text").val(encodeURIComponent($("#search-text").val()));
    $("#search-form").submit();
  });
});
Prakash Rajendran
sumber
4
Jquery dan teknologi sisi klien tidak ada hubungannya dengan MVC, validasi terjadi di sisi server dengan kerangka kerja MVC. Ini bukan jawaban yang valid
diegosasw
1
Mengingat bahwa Microsoft benar-benar mengabaikan atribut AllowHtml, dan mengingat bahwa satu-satunya solusi sisi server yang bisa diterapkan adalah mengganti fungsionalitas pengikat model default, saya berpendapat bahwa pengkodean sisi klien adalah opsi yang sangat valid.
Jonathan