JSON.parse กับ eval ()


95

My Spider Sense เตือนฉันว่าการใช้eval()เพื่อแยกวิเคราะห์ JSON ขาเข้าเป็นความคิดที่ไม่ดี ฉันแค่สงสัยว่าJSON.parse()- ที่ฉันคิดว่าเป็นส่วนหนึ่งของ JavaScript ไม่ใช่ฟังก์ชันเฉพาะเบราว์เซอร์จะปลอดภัยกว่าหรือไม่


ประสิทธิภาพที่ชาญฉลาดJSON.parseเร็วกว่าevalอย่างน้อยที่สุดใน V8 (เครื่องยนต์ JS ของ Chromium) แหล่ง
พอล

คำตอบ:


110

คุณมีความเสี่ยงที่จะถูกโจมตีมากขึ้นหากใช้eval: JSON เป็นส่วนย่อยของ Javascript และ json.parse จะแยกวิเคราะห์ JSON ในขณะที่evalจะเปิดประตูไว้สำหรับนิพจน์ JS ทั้งหมด


"คุณเสี่ยงต่อการถูกโจมตีมากกว่า"ฉันไม่เห็นด้วยอย่างยิ่ง!
Hydroper

5
ขอโทษ Matheus ฉันต้องเห็นด้วย ปัญหาคือเมื่อคุณใช้ eval () เพื่อตีความ "อินพุตของผู้ใช้" ซึ่งเป็นแหล่งที่มาภายนอกจาก JavaScript ของคุณ (รวมถึงค่าที่ส่งคืนจาก servlets หรือบริการเว็บอื่น ๆ ที่คุณเรียก) คุณไม่สามารถรับประกันได้ว่าผู้ใช้ไม่ได้ป้อน JavaScript ที่เป็นอันตรายลงในแอปไคลเอ็นต์ของคุณโดยตรงหรือโดยอ้อมเนื่องจากข้อมูลที่ไม่ผ่านการตรวจสอบที่เก็บไว้ในฐานข้อมูลของเซิร์ฟเวอร์จากนั้นส่งต่อไปยังโปรแกรมของคุณผ่านการเรียกแบบ AJAX คุณอาจยังต้องตรวจสอบความถูกต้องของแต่ละช่องเพื่อหลีกเลี่ยงการโจมตี "ผู้ช่วยที่สับสน" แต่การใช้ JSON.parse เป็นขั้นตอนแรกที่ดี
JackLThornton

1
หลักฐาน @Hydro สั้นของแนวคิด: eval('alert(1)');ลอง
Valerio Bozz

37

ทั้งหมด JSON.parseการใช้งานน่าจะใช้มากที่สุดeval()

JSON.parseใช้วิธีแก้ปัญหาของ Douglas Crockfordซึ่งใช้eval()ตรงบรรทัดที่ 497497

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

j = eval('(' + text + ')');

ข้อดีของJSON.parseมันคือการตรวจสอบว่าอาร์กิวเมนต์นั้นถูกต้องไวยากรณ์ JSON


56
ใช่ยกเว้นว่าบรรทัดก่อนหน้านั้นจะยืนยันว่าเป็นสตริงที่ปลอดภัยและถูกต้อง
nickf

6
ฉันทดสอบJSON.parse()ใน Firefox 28 และ Chromium 33 บนระบบ Linux Mint ของฉัน เร็วกว่าeval()ใน Firefox 2 เท่าและเร็วกว่า Chromium ถึง 4 เท่า ฉันไม่แน่ใจว่าคุณกำลังโพสต์ซอร์สโค้ดอะไร แต่ไม่ใช่สิ่งเดียวกันในเบราว์เซอร์ของฉัน
jbo5112

@plodder "ความได้เปรียบ" อาจไม่ถูกที่จะทำการยืนยันนั้น
mmm

2
เบราว์เซอร์สมัยใหม่ให้JSON.parse()การใช้งานแบบเนทีฟซึ่งปลอดภัยและเร็วกว่าeval()ตัวแยกวิเคราะห์ที่ใช้
Mohammad Alhashash

15

ไม่ใช่ทุกเบราว์เซอร์ที่รองรับ JSON แบบเนทีฟดังนั้นจะมีบางครั้งที่คุณต้องใช้eval() กับสตริง JSON ใช้โปรแกรมแยกวิเคราะห์ JSON จากhttp://json.orgซึ่งจัดการทุกอย่างได้ง่ายขึ้นมากสำหรับคุณ

Eval() เป็นความชั่วร้าย แต่กับเบราว์เซอร์บางตัวมันเป็นความชั่วร้ายที่จำเป็น แต่คุณสามารถหลีกเลี่ยงได้ที่ไหนทำ !!!!!


12

มีความแตกต่างระหว่างสิ่งที่ JSON.parse () และ eval () จะยอมรับ ลองประเมินสิ่งนี้:

var x = "{\" shoppingCartName \ ": \" shopping_cart: 2000 \ "}"

eval(x)         //won't work
JSON.parse(x)   //does work

ดูตัวอย่างนี้


1
eval ไม่ทำงานเนื่องจากจะแยกวิเคราะห์สตริงเป็นคำสั่งรหัสดังนั้นการพิจารณา "{... }" เป็นนิพจน์รหัสแทนนิพจน์การประกาศค่า หากคุณลบความคลุมเครือ (ตัวอย่างเช่น "[{.... }]") ไม่มีข้อสงสัยเกี่ยวกับลักษณะของนิพจน์และ eval จะสร้างอาร์เรย์ที่มี objet ที่แยกวิเคราะห์
Charles HETIER

1
ใช่. ตามเนื้อผ้า x จะอยู่ในวงเล็บ: eval ("(" + x + ")") สิ่งที่ฉันพูดยังคงมีอยู่: ไม่มีความคลุมเครือเมื่อใช้ JSON.parse ()
Jeff Lowery

9

หากคุณแยกวิเคราะห์ JSON ด้วย evalคุณจะอนุญาตให้สตริงที่แยกวิเคราะห์มีอะไรก็ได้ดังนั้นแทนที่จะเป็นเพียงชุดข้อมูลคุณอาจพบว่าตัวเองกำลังเรียกใช้ฟังก์ชันหรืออะไรก็ตาม

นอกจากนี้ JSON ยังparseยอมรับพารามิเตอร์ aditional reviver ที่ให้คุณระบุวิธีจัดการกับค่าบางอย่างเช่นวันที่ (ข้อมูลเพิ่มเติมและตัวอย่างในเอกสารอินไลน์ที่นี่ )


4

JSON เป็นเพียงส่วนย่อยของ JavaScript แต่evalประเมินภาษา JavaScript แบบเต็มไม่ใช่เฉพาะส่วนย่อยที่เป็น JSON


ใช่ฉันรู้ว่า คุณหมายความว่า JSON.parse () ประเมินเฉพาะ JSON และล้มเหลวในข้อมูลขาเข้าอื่น ๆ ทั้งหมดหรือไม่ หรือเป็นเพียงกระดาษห่อหุ้มสำหรับ: var myObject = eval ('(' + responseText + ')'); ??
Kevin Major

6
@Kevin Major: ใช่การใช้งานโดยกำเนิดJSON.parse(นำไปใช้โดยตรงกับเครื่องมือ JavaScript) จะแยกวิเคราะห์เฉพาะ JSON แต่การใช้งานอื่น ๆ ที่ไม่ได้ใช้โดยกำเนิดจะใช้การตรวจสอบความถูกต้องและใช้evalเพื่อเหตุผลด้านประสิทธิภาพ
Gumbo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.