Jak napisać niezakodowane Json do mojego widoku przy użyciu Razor?

153

Próbuję napisać obiekt jako JSON do mojego widoku Asp.Net MVC przy użyciu Razor, na przykład:

<script type="text/javascript">
  var potentialAttendees = @Json.Encode(Model.PotentialAttendees);
</script>

Problem polega na tym, że w danych wyjściowych kodowany jest JSON, a mojej przeglądarce się to nie podoba. Na przykład:

<script type="text/javascript">
    var potentialAttendees = [{&quot;Name&quot;:&quot;Samuel Jack&quot;},];
</script>

Jak sprawić, by Razor emitował niezakodowane JSON?

Samuel Jack
źródło

Odpowiedzi:

190

Ty robisz:

@Html.Raw(Json.Encode(Model.PotentialAttendees))

W wersjach wcześniejszych niż Beta 2 robiłeś to tak:

@(new HtmlString(Json.Encode(Model.PotentialAttendees)))
Lorenzo
źródło
3
Co mogę zrobić, jeśli chcę mieć zakodowany tekst we właściwościach moich obiektów? \, {\ "UrlPart \": \ "TjcolklFX5c \", \ "Title \": \ "When Mama Isn \ u0027t Home \"}, {\ "Na przykład. natywna dekalracja ciągu znaków zmiennej a = '' to samo dotyczy „”. anny pomysł?
SomeRandomName
@SomeRandomName możesz użyć javascriptserializerdo tego @Html.Raw(javascriptSerializerObjecct.Serialize(myObject))
vikscool
Jesteśmy w 2017 roku, używamy MVC 5 i ta odpowiedź jest nadal doskonała!
Gabriel Espinoza
Ta odpowiedź jest jedyną, która działa doskonale. Dzięki!
Jean-Paul
43

Newtonsoft JsonConvert.SerializeObjectnie zachowuje się tak samo, Json.Encodea zrobienie tego, co sugeruje @ david-k-egghead, otwiera cię na ataki XSS .

Upuść ten kod do widoku Razor, aby zobaczyć, że używanie Json.Encodejest bezpieczne i że Newtonsoft można zabezpieczyć w kontekście JavaScript, ale nie jest to bez dodatkowej pracy.

<script>
    var jsonEncodePotentialAttendees = @Html.Raw(Json.Encode(
        new[] { new { Name = "Samuel Jack</script><script>alert('jsonEncodePotentialAttendees failed XSS test')</script>" } }
    ));
    alert('jsonEncodePotentialAttendees passed XSS test: ' + jsonEncodePotentialAttendees[0].Name);
</script>
<script>
    var safeNewtonsoftPotentialAttendees = JSON.parse(@Html.Raw(HttpUtility.JavaScriptStringEncode(JsonConvert.SerializeObject(
        new[] { new { Name = "Samuel Jack</script><script>alert('safeNewtonsoftPotentialAttendees failed XSS test')</script>" } }), addDoubleQuotes: true)));
    alert('safeNewtonsoftPotentialAttendees passed XSS test: ' + safeNewtonsoftPotentialAttendees[0].Name);
</script>
<script>
    var unsafeNewtonsoftPotentialAttendees = @Html.Raw(JsonConvert.SerializeObject(
        new[] { new { Name = "Samuel Jack</script><script>alert('unsafeNewtonsoftPotentialAttendees failed XSS test')</script>" } }));
    alert('unsafeNewtonsoftPotentialAttendees passed XSS test: ' + unsafeNewtonsoftPotentialAttendees[0].Name);
</script>

Zobacz też:

Jeremy Cook
źródło
Czy masz jakiś pomysł, kiedy dodali Json.Encode? Nie zdawałem sobie sprawy, że w rzeczywistości istnieje bezpieczny sposób wstawienia pliku JSON na stronie i wiem, że w przeszłości przeprowadziłem wiele badań na ten temat.
Chris Marisic
1
Json.Encodeistnieje, odkąd pamiętam, ale wadą jest to, że wykorzystuje implementację firmy Microsoft, która generuje niestandardowe daty (i może robić inne uciążliwe rzeczy). Używam i zachęcam do korzystania z Newtonsoft w JsonConvert.SerializeObjectpołączeniu z odpowiednim ucieczką, ponieważ ma lepsze wyjście.
Jeremy Cook,
2
Cieszę się, że przewinęłam w dół. Natychmiast zobaczyłem zaakceptowaną odpowiedź, miałem nadzieję, że jest na to bezpieczny sposób.
mroźno cudowne
Wersja HttpUtility.JavaScriptStringEncode również koduje znaki cudzysłowu w formacie JSON, czyniąc je nieprawidłowymi, jeśli jest używany bezpośrednio w skrypcie [type = 'application / json'], a szkoda.
Pete Kirkham
1
Uwaga dla przyszłego siebie: ten, którego chcesz użyć, to: @ Html.Raw (Json.Encode ())
Pangamma
12

Korzystanie z Newtonsoft

<script type="text/jscript">
  var potentialAttendees  = @(Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.PotentialAttendees)))
</script>
Ravi Ram
źródło
1
Jest to potencjalnie podatne na luki w zabezpieczeniach XSS, które Json.Encode naprawia, ale możesz zastąpić, JsonSerializerSettings.StringEscapeHandlingaby włączyć kodowanie. stackoverflow.com/a/50336590/6950124
Kevin Secrist