Zezwalaj użytkownikowi na wprowadzanie kodu HTML w ASP.NET MVC - ValidateInput lub AllowHtml

120

Jak mogę zezwolić użytkownikowi na wprowadzanie kodu HTML do określonego pola przy użyciu ASP.net MVC.

Mam długi formularz z wieloma polami, które są mapowane na ten złożony obiekt w kontrolerze.

Chciałbym, aby jedno pole (opis) zezwalało na HTML, na którym później wykonam własną higienę.

Rabin
źródło
3
Dla przyszłych odwiedzających: odpowiedzi IMHO, Chrisa J lub Eugene Bosikov są lepsze niż te zaakceptowane dla późniejszych wersji ASP.NET MVC, zwłaszcza jeśli chcesz zezwolić na HTML tylko w jednym polu.
lc.

Odpowiedzi:

163

Dodaj następujący atrybut akcja (post) w kontrolerze, dla którego chcesz zezwolić na HTML:

[ValidateInput(false)] 

Edycja: zgodnie z komentarzami Charlino :

W pliku web.config ustaw używany tryb sprawdzania poprawności. Zobacz MSDN :

<httpRuntime requestValidationMode="2.0" />

Edycja września 2014: Zgodnie z komentarzami sprintera252 :

Powinieneś teraz użyć [AllowHtml]atrybutu. Zobacz poniżej z MSDN :

W przypadku aplikacji ASP.NET MVC 3, gdy musisz opublikować kod HTML z powrotem do modelu, nie używaj ValidateInput (false), aby wyłączyć weryfikację żądania. Po prostu dodaj [AllowHtml] do właściwości modelu, na przykład:

public class BlogEntry {
    public int UserId {get;set;}
    [AllowHtml] 
    public string BlogText {get;set;}
 }
Kelsey
źródło
1
Jeśli korzystasz z .NET 4, musisz to również ustawić <httpRuntime requestValidationMode="2.0" />w pliku web.config.
Charlino
3
Czy naprawdę nie ma rozwiązania dla platformy .NET 4, które nie obejmuje obniżenia trybu sprawdzania poprawności żądań?
bzlm
20
MSDN ( msdn.microsoft.com/de-de/magazine/hh708755.aspx ) mówi, że nie należy używać ValidateInpute i zamiast tego przyjmować AllowHtmlAttribute. (Nie znalazłem wersji angielskiej)
Alexander Schmidt
8
Dokonano edycji, aby, miejmy nadzieję, zająć się 3 głosami negatywnymi, które zostały niedawno oddane ... to była 4-letnia odpowiedź :)
Kelsey
1
@ djack109 Zazwyczaj model EF nie jest używany jako model widoku. Napisałbyś osobną klasę, która reprezentuje rzeczywiste dane dla operacji CRUD. W ten sposób podczas regeneracji modelu EF6 nic nie jest tracone. Powinieneś także odchudzić modele, aby miały tylko właściwości potrzebne do wykonania danego zadania.
Allen Clark Copeland Jr
131

A co z [AllowHtml]atrybutem powyżej właściwości?

cryss
źródło
5
Wydaje mi się, że jest to znacznie lepszy sposób, aby uniknąć zmiany jakichkolwiek zachowań globalnych. Właśnie rozwiązałem swój problem, dodając ten atrybut do właściwości w moim modelu.
Jonathan Sayce,
2
Całkowicie zgadzam się z rozwiązaniem Chrisa, nie ma powodu, aby wyłączać walidację html dla całej aplikacji, jeśli potrzebujesz tylko jednej właściwości w modelu, aby móc akceptować dane wejściowe HTML. Usunięcie walidacji w pliku web.config otworzy dużą lukę w zabezpieczeniach Twojej aplikacji.
Miguel
1
Niestety to nie działa, jeśli używasz MetadataTypeAttribute
dav_i
@dav_i: To rozwiązanie działa dobrze MetadataTypeAttributei jest preferowane, ponieważ zezwala tylko na HTML w poszczególnych polach, a nie w całym obiekcie.
Gone Coding
@TrueBlueAussie, próbowałem godzinami w moim środowisku mvc 4.0 i chociaż AllowHtml powinien działać, nie działa. Musiałem przyznać się do porażki i wybrać mniej bezpieczną opcję, jaką są spodnie. AllowHtml po prostu nie działa z użyciem MetadataTypeAttribute
julian guppy,
42

Dodaj do modelu:

using System.Web.Mvc;

I do twojej własności

        [AllowHtml]
        [Display(Name = "Body")]
        public String Body { get; set; }

Ten kod z mojego punktu widzenia jest najlepszym sposobem uniknięcia tego błędu. Jeśli używasz edytora HTML, nie będziesz mieć problemów z bezpieczeństwem, ponieważ jest on już ograniczony.

Eugene Bosikov
źródło
9

Dodanie [AllowHtml]określonej właściwości jest zalecanym rozwiązaniem, ponieważ istnieje wiele blogów i komentarzy sugerujących obniżenie poziomu bezpieczeństwa, co powinno być niedopuszczalne.

Dodając to, struktura MVC pozwoli na trafienie kontrolera i wykonanie kodu w tym kontrolerze.

Zależy to jednak od kodu, filtrów itp., W jaki sposób generowana jest odpowiedź i czy istnieje dalsza weryfikacja, która może wywołać inny podobny błąd.

W każdym razie dodanie [AllowHtml]atrybutu jest właściwą odpowiedzią, ponieważ pozwala na deserializację html w kontrolerze. Przykład w Twoim modelu widoku:

[AllowHtml]
public string MessageWithHtml {get; set;}
diegosasw
źródło
8

Napotkałem ten sam problem, chociaż dodałem [System.Web.Mvc.AllowHtml]do dotyczącego właściwości, jak opisano w niektórych odpowiedziach.

W moim przypadku mam UnhandledExceptionFilterklasę, która uzyskuje dostęp do obiektu Request przed przeprowadzeniem walidacji MVC (a zatem AllowHtml nie ma wpływu) i ten dostęp wywołuje [HttpRequestValidationException] A potentially dangerous Request.Form value was detected from the client.

Oznacza to, że dostęp do niektórych właściwości obiektu Request niejawnie wywołuje walidację (w moim przypadku jest to Paramswłaściwość).

Rozwiązanie zapobiegające sprawdzaniu poprawności jest udokumentowane w witrynie MSDN

Aby wyłączyć sprawdzanie poprawności żądania dla określonego pola w żądaniu (na przykład dla elementu wejściowego lub wartości ciągu zapytania), wywołaj metodę Request.Unvalidated po otrzymaniu elementu, jak pokazano w poniższym przykładzie

Dlatego jeśli masz taki kod

var lParams = aRequestContext.HttpContext.Request.Params;
if (lParams.Count > 0)
{
  ...

zmień to na

var lUnvalidatedRequest = aRequestContext.HttpContext.Request.Unvalidated;

var lForm = lUnvalidatedRequest.Form;
if (lForm.Count > 0)
{
  ...

lub po prostu użyj Formwłaściwości, która nie wydaje się uruchamiać walidacji

var lForm = aRequestContext.HttpContext.Request.Form;
if (lForm.Count > 0)
{
  ...
WIARYGODNOŚĆ
źródło
1
Dzięki! Request.Unvalidated było jedynym rozwiązaniem, które działało dla mnie.
Petter Ivarsson,
3

Jeśli chcesz zezwolić na wprowadzanie html dla parametru metody akcji (w przeciwieństwie do „właściwości modelu”), nie ma na to wbudowanego sposobu, ale możesz to łatwo osiągnąć za pomocą niestandardowego spinacza modelu:

public ActionResult AddBlogPost(int userId,
    [ModelBinder(typeof(AllowHtmlBinder))] string htmlBody)
{
    //...
}

Kod AllowHtmlBinder:

public class AllowHtmlBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var request = controllerContext.HttpContext.Request;
        var name = bindingContext.ModelName;
        return request.Unvalidated[name]; //magic happens here
    }
}

Znajdź pełny kod źródłowy i wyjaśnienie w moim poście na blogu: https://www.jitbit.com/alexblog/273-aspnet-mvc-allowing-html-for-particular-action-parameters/

Alex
źródło
1
Wersja Unvalidated wydaje się być dostępna tylko w frameworku 4.5 i nowszych.
Ben
@Ben dobrze! Sprawdź to zmodyfikowane rozwiązanie. stackoverflow.com/questions/59483284/…
om-ha
3

Kodowanie URL danych działa również dla mnie

Na przykład

var data = '<b> Witaj </b>'

W przeglądarce wywołaj encodeURIComponent (dane) przed wysłaniem

Na serwerze wywołaj HttpUtility.UrlDecode (received_data), aby zdekodować

W ten sposób możesz dokładnie kontrolować, który obszar pól może mieć kod HTML

smjhunt
źródło
jak dotąd najłatwiejszy sposób
N1gthm4r3
1

Spotkałem się z tym problemem podczas tworzenia witryny e-commerce przy użyciu NopCommerce, otrzymałem to rozwiązanie na 3 różne sposoby, tak jak poprzednie odpowiedzi. Ale zgodnie ze strukturą NopCommerce nie znalazłem tych trzech na raz. Właśnie zobaczyłem, że właśnie tam używają [AllowHtml]i działa dobrze, z wyjątkiem każdego problemu. Jak poprzednio zadane pytanie

Osobiście nie wolę, [ValidateInput(false)]ponieważ pomijam sprawdzanie całości modelu, co jest niebezpieczne. Ale jeśli ktoś tylko napisze , zajrzyj tutaj

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

wtedy po prostu pomija tylko jedną właściwość i zezwala tylko na określoną właściwość i nie sprawdza prawie wszystkich innych jednostek. Dlatego wydaje się lepszy od mojego.

gdmanandamohon
źródło
1

W moim przypadku atrybut AllowHtml nie działał w połączeniu z filtrem akcji OutputCache. Ta odpowiedź rozwiązała problem za mnie. Mam nadzieję, że to komuś pomoże.

jd4w9
źródło
1

Możesz użyć [AllowHtml]do swojego projektu na przykład

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

Aby użyć tego kodu do biblioteki klas, należy zainstalować ten pakiet

Install-Package Microsoft.AspNet.Mvc

Po użyciu tego using

using System.Web.Mvc;
Diako Hasani
źródło
0

Żadna z odpowiedzi tutaj niestety nie zadziałała.

Skończyło się na tym, że użyłem niestandardowego powiązania modelu i użyłem zewnętrznego środka dezynfekującego.

Zobacz mój własny odpowiedział na pytanie tutaj .

om-ha
źródło