ฉันจะเขียน Json ที่ไม่มีการเข้ารหัสลงในมุมมองของฉันโดยใช้มีดโกนได้อย่างไร


153

ฉันพยายามเขียนวัตถุเป็น JSON ไปยัง Asp.Net MVC View ของฉันโดยใช้มีดโกนเช่น:

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

ปัญหาคือว่าในการส่งออก JSON ถูกเข้ารหัสและเบราว์เซอร์ของฉันไม่ชอบมัน ตัวอย่างเช่น:

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

ฉันจะให้มีดโกนปล่อย JSON ที่ไม่มีการเข้ารหัสได้อย่างไร

คำตอบ:


190

คุณทำ:

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

ในรุ่นก่อนหน้า Beta 2 คุณทำเช่นนี้:

@(new HtmlString(Json.Encode(Model.PotentialAttendees)))

3
ฉันต้องทำอย่างไรหากฉันต้องการข้อความที่เข้ารหัสในคุณสมบัติออบเจ็กต์ของฉัน \, {\ "UrlPart \": \ "TjcolklFX5c \", \ "ชื่อ \": \ "เมื่อ Mama Isn \ u0027t Home \"}, {\ "ตัวอย่างเช่นนี้จะทำให้ beacause js คิดว่า 'กำลังหลบหนี การถอดรหัสสตริงพื้นเมืองของ var a = '' เหมือนกันใช้กับ "" ความคิด anny?
SomeRandomName

@SomeRandomName คุณสามารถใช้javascriptserializerสำหรับสิ่งนั้นได้ @Html.Raw(javascriptSerializerObjecct.Serialize(myObject))
vikscool

เราอยู่ในปี 2560 ใช้ MVC 5 และคำตอบนี้ยังสมบูรณ์แบบ!
Gabriel Espinoza

คำตอบนี้เป็นคำตอบเดียวที่ทำงานได้อย่างสมบูรณ์ ขอบคุณ!
Jean-Paul

43

Newtonsoft ของJsonConvert.SerializeObjectไม่ประพฤติเช่นเดียวกับJson.Encodeและทำในสิ่งที่ @ david-K-ปัญญาชนแสดงให้เห็นเปิดให้คุณถึงโจมตี XSS

วางรหัสนี้ในมุมมองมีดโกนเพื่อดูว่าการใช้Json.Encodeนั้นปลอดภัยและ Newtonsoft สามารถสร้างความปลอดภัยในบริบท JavaScript แต่ไม่ได้โดยไม่มีงานพิเศษ

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

ดูสิ่งนี้ด้วย:


คุณมีความคิดใด ๆ เมื่อพวกเขาเพิ่ม Json.Encode? ฉันไม่ทราบว่าจริง ๆ แล้วมีวิธีที่ปลอดภัยในการแทรก json บนหน้าเว็บและฉันรู้ว่าฉันได้ทำการวิจัยจำนวนมากในอดีต
Chris Marisic

1
Json.Encodeได้รับตราบใดที่ฉันจำได้ แต่ข้อเสียคือมันใช้การดำเนินการของ Microsoft ที่ส่งออกวันที่ที่ไม่ได้มาตรฐาน (และอาจทำสิ่งที่น่ารำคาญอื่น ๆ ) ฉันใช้และสนับสนุนให้ใช้ Newtonsoft JsonConvert.SerializeObjectรวมกับการหลบหนีที่เหมาะสมเพราะมันมีผลลัพธ์ที่ดีกว่า
Jeremy Cook

2
ดีใจที่ฉันเลื่อนลง ทันทีที่ฉันเห็นคำตอบที่ยอมรับฉันหวังว่าจะมีวิธีที่ปลอดภัยในการทำเช่นนี้
frostymarvelous

รุ่น HttpUtility.JavaScriptStringEncode ยังเข้ารหัสเครื่องหมายคำพูดใน JSON ทำให้การแสดงผลไม่ถูกต้องหากใช้โดยตรงในสคริปต์ [type = 'application / json'] ซึ่งน่าเสียดาย
Pete Kirkham

1
หมายเหตุสำหรับตนเองในอนาคต: สิ่งที่คุณต้องการใช้คือ: @ Html.Raw (Json.Encode ())
Pangamma

12

ใช้ Newtonsoft

<script type="text/jscript">
  var potentialAttendees  = @(Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.PotentialAttendees)))
</script>

1
นี่อาจเป็นช่องโหว่ของ XSS ที่ Json.Encode แก้ไข แต่คุณสามารถแทนที่JsonSerializerSettings.StringEscapeHandlingเพื่อเปิดใช้งานการเข้ารหัส stackoverflow.com/a/50336590/6950124
Kevin Secrist
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.