Comment écrire du Json non codé sur ma vue à l'aide de Razor?

153

J'essaie d'écrire un objet au format JSON sur ma vue Asp.Net MVC en utilisant Razor, comme ceci:

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

Le problème est que dans la sortie, le JSON est encodé et mon navigateur ne l'aime pas. Par exemple:

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

Comment faire pour que Razor émette du JSON non codé?

Samuel Jack
la source

Réponses:

190

Tu fais:

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

Dans les versions antérieures à la bêta 2, vous faisiez comme:

@(new HtmlString(Json.Encode(Model.PotentialAttendees)))
Lorenzo
la source
3
Que puis-je faire si je veux du texte encodé dans les propriétés de mes objets? \, {\ "UrlPart \": \ "TjcolklFX5c \", \ "Title \": \ "When Mama Isn \ u0027t Home \"}, {\ "Par exemple. Cela cassera car js pense que 'échappe au Décalage de la chaîne native de var a = '' idem pour "". anny idea?
SomeRandomName
@SomeRandomName que vous pouvez utiliser javascriptserializerpour cela comme @Html.Raw(javascriptSerializerObjecct.Serialize(myObject))
vikscool
Nous sommes en 2017, en utilisant MVC 5 et cette réponse est toujours parfaite!
Gabriel Espinoza
Cette réponse est la seule qui fonctionne parfaitement. Merci!
Jean-Paul
43

Newtonsoft JsonConvert.SerializeObjectne se comporte pas de la même manière Json.Encodeet faire ce que @ david-k-egghead suggère vous ouvre aux attaques XSS .

Déposez ce code dans une vue Razor pour voir que l'utilisation Json.Encodeest sûre et que Newtonsoft peut être sécurisé dans le contexte JavaScript, mais n'est pas sans travail supplémentaire.

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

Voir également:

Jeremy Cook
la source
Avez-vous une idée quand ils ont ajouté Json.Encode? Je ne savais pas qu'il y avait en fait un moyen sûr d'insérer json sur la page et je sais que j'ai fait beaucoup de recherches à ce sujet dans le passé.
Chris Marisic
1
Json.Encodea été aussi longtemps que je me souvienne, mais l'inconvénient est qu'il utilise l'implémentation de Microsoft qui produit des dates non standard (et peut faire d'autres choses gênantes). J'utilise et j'encourage l'utilisation de Newtonsoft JsonConvert.SerializeObjectcombinée avec un échappement approprié car il a un meilleur rendement.
Jeremy Cook
2
Heureux d'avoir fait défiler vers le bas. Immédiatement, j'ai vu la réponse acceptée, j'ai espéré qu'il y avait un moyen sûr de le faire.
frostymarvelous
La version HttpUtility.JavaScriptStringEncode encode également les guillemets dans le JSON, le rendant invalide s'il est utilisé directement dans un script [type = 'application / json'], ce qui est dommage.
Pete Kirkham
1
Note au futur moi: celui que vous souhaitez utiliser est le suivant: @ Html.Raw (Json.Encode ())
Pangamma
12

Utilisation de Newtonsoft

<script type="text/jscript">
  var potentialAttendees  = @(Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.PotentialAttendees)))
</script>
Ravi Ram
la source
1
Ceci est potentiellement vulnérable aux vulnérabilités XSS corrigées par Json.Encode, mais vous pouvez remplacer le JsonSerializerSettings.StringEscapeHandlingpour activer l'encodage. stackoverflow.com/a/50336590/6950124
Kevin Secrist