Pytanie ASP.NET MVC Potencjalnie niebezpieczna wartość Request.Form została wykryta przez klienta podczas korzystania z niestandardowego narzędzia do modelowania


Tutaj pojawia się błąd:

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

Jak mogę zezwolić tylko na wybór wartości? to znaczy

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

76
2018-06-22 19:08


pochodzenie


Możliwy duplikat Potencjalnie niebezpieczna wartość Request.Form została wykryta przez klienta, nie ma znaczenia, czy to Webforms czy MVC. - Erik Philips
Dzięki, ale nie spojrzałeś na mój problem, ponieważ jest inny - D-W
Taki sam dokładny problem root, jedyna różnica polega na tym, że MVC może mieć specyficzne sposoby radzenia sobie z tym problemem. - Erik Philips


Odpowiedzi:


Masz kilka opcji.

W modelu dodaj ten atrybut do każdej właściwości, która wymaga zezwolenia na HTML - najlepszy wybór

using System.Web.Mvc;

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

W akcji kontrolera dodaj ten atrybut, aby zezwolić na cały HTML

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

Brute force w web.config - zdecydowanie nie polecam

W pliku web.config w tagach wstaw element httpRuntime z atrybutem requestValidationMode = "2.0". Dodaj także atrybut validateRequest = "false" w elemencie strony.

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

Więcej informacji: http://davidhayden.com/blog/dave/archive/2011/01/16/AllowHtmlAttributeASPNETMVC3.aspx

Powyższe działa dla użycia domyślnego modelu do modelowania.

Custom ModelBinder

Wygląda na to, że wywołanie metody bindingContext.ValueProvider.GetValue () w powyższym kodzie zawsze potwierdza dane, niezależnie od atrybutów. Kopiowanie do źródeł ASP.NET MVC ujawnia, że ​​DefaultModelBinder najpierw sprawdza, czy żądanie sprawdzania poprawności jest wymagane, a następnie wywołuje metodę bindingContext.UnvalidatedValueProvider.GetValue () z parametrem wskazującym, czy weryfikacja jest wymagana, czy nie.

Niestety nie możemy użyć żadnego z kodu szkieletowego, ponieważ jest on zapieczętowany, prywatny lub jakikolwiek inny, aby chronić nieświadomych programistów przed robieniem niebezpiecznych rzeczy, ale nie jest to zbyt trudne do stworzenia działającego niestandardowego spoiwa modelu, który respektuje atrybuty AllowHtml i 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...
        }
    }
}

Drugi wymagany element to sposób na odzyskanie wartości niezweryfikowanej. W tym przykładzie używamy metody rozszerzenia dla klasy 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);
    }
}

Więcej informacji na ten temat na http://blogs.taiga.nl/martijn/2011/09/29/custom-model-binders-and-request-validation/


188
2018-06-23 06:03



Mam to na kontroler [HttpPost, ValidateInput (false)] i nadal otrzymuję błąd - D-W
Zobacz moją poprawioną odpowiedź w sposób omijany podczas korzystania z niestandardowego modelu do modelowania - ericdc
Dzięki, ale nie podoba mi się ta linia bindingContext.GetValueFromValueProvider - D-W
GetValueFromValueProvider musi znajdować się w publicznej klasie statycznej. Sprawdź zmiany powyżej. - ericdc
Ta, valueProviderResult ponownie zeruje? var valueProviderResult = bindingContext.GetValueFromValueProvider (shouldPerformRequestValidation); - D-W


Próbować:

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

27
2018-06-24 20:00



Kiedy próbuję tego, otrzymuję wyjątek, który mówi: Nie-invocable członek "System.web.HttpRequestBase.Unvalidated" nie może być używany jak metoda. Czy to się zmieniło? - Stack0verflow
Druga linia powinna być naprawdę var re = request.Unvalidated.Form["ConfirmationMessage"]; - Stack0verflow


Rozszerzając odpowiedź z @ D-W, w moim sterowniku Edit, w iteracji wartości formularza, musiałem zastąpić wszystkie wystąpienia Request.Params.AllKeys z Request.Unvalidated.Form.AllKeys i wszystkie wystąpienia Request[key] z Request.Unvalidated.Form[key].

To było jedyne rozwiązanie, które zadziałało dla mnie.


0
2018-02-28 17:12





Oto kroki do kodowania na poziomie klienta i dekodowania go na poziomie serwera:

  1. Opublikuj formularz za pomocą metody przesyłania jquery.

  2. W polu tekstowym kliknij zakodować pole zdarzenia, które chcesz opublikować na serwerze. Przykład:

    $("#field").val(encodeURIComponent($("#field").val()))
    $("#formid").submit();
    
  3. Na poziomie kontrolera dostęp do wszystkich wartości id form za pomocą

    HttpUtility.UrlDecode(Request["fieldid"])
    

Przykładowy przykład:

  • Poziom kontrolera:

    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));
    }
    
  • Poziom klienta:

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

W funkcji Document Ready:

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

-3
2017-07-01 09:14



Jquery i technologia po stronie klienta nie ma nic wspólnego z MVC, walidacja odbywa się po stronie serwera ze strukturą MVC. To nie jest poprawna odpowiedź - iberodev
Biorąc pod uwagę, że Microsoft dosłownie ignoruje atrybut AllowHtml i biorąc pod uwagę, że jedynym możliwym do zastosowania rozwiązaniem po stronie serwera jest zastąpienie funkcjonalności domyślnego modułu wiążącego modelu, argumentowałbym, że kodowanie po stronie klienta jest całkowicie poprawną opcją. - Jonathan