JSON.parse so với eval ()


94

Spider Sense của tôi cảnh báo tôi rằng việc sử dụng eval()để phân tích cú pháp JSON đến là một ý tưởng tồi. Tôi chỉ tự hỏi liệu JSON.parse()- cái mà tôi cho là một phần của JavaScript chứ không phải một chức năng dành riêng cho trình duyệt - có an toàn hơn không.


Hiệu suất khôn ngoan, JSON.parsenhanh hơn eval, ít nhất là trong V8 (công cụ JS của Chromium). Nguồn .
Paul

Câu trả lời:


110

Bạn dễ bị tấn công hơn nếu sử dụng eval: JSON là một tập hợp con của Javascript và json.parse chỉ phân tích cú pháp JSON trong khi evalsẽ mở cửa cho tất cả các biểu thức JS.


"Bạn dễ bị tấn công hơn" , tôi hoàn toàn không đồng ý!
Hydroper

4
Xin lỗi, Matheus, tôi phải đồng ý. Vấn đề là khi bạn đang sử dụng eval () để diễn giải "đầu vào của người dùng" - là BẤT KỲ nguồn nào bên ngoài từ JavaScript của bạn (bao gồm các giá trị trả về từ các servlet hoặc các dịch vụ web khác mà bạn đã gọi). Bạn không thể đảm bảo người dùng không nhập JavaScript độc hại trực tiếp vào ứng dụng khách của bạn hoặc gián tiếp do dữ liệu chưa được kiểm chứng được lưu trữ trong cơ sở dữ liệu của máy chủ và sau đó được chuyển đến chương trình của bạn thông qua lệnh gọi kiểu AJAX. Bạn vẫn có thể cần xác thực các trường riêng lẻ để tránh các cuộc tấn công "phó chủ tịch nhầm lẫn", nhưng sử dụng JSON.parse là một bước đầu tiên tốt.
JackLThornton

1
@Hydro Bằng chứng ngắn gọn về khái niệm: thử eval('alert(1)');.
Valerio Bozz

37

Tất cả các JSON.parsetriển khai có nhiều khả năng sử dụngeval()

JSON.parsedựa trên giải pháp của Douglas Crockford , được sử dụng eval()ngay tại dòng 497 .

// 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 + ')');

Ưu điểm của JSON.parsenó là nó xác minh đối số là cú pháp JSON chính xác.


56
vâng, ngoại trừ dòng ngay trước đó xác minh rằng đó là một chuỗi an toàn và hợp lệ.
nickf

6
Tôi đã thử nghiệm JSON.parse()trong Firefox 28 và Chromium 33 trên hệ thống Linux Mint của mình. Nó nhanh gấp 2 lần eval()trong Firefox và nhanh gấp 4 lần trong Chromium. Tôi không chắc bạn đang đăng mã nguồn nào, nhưng chúng không giống nhau trong trình duyệt của tôi.
jbo5112

@plodder "lợi thế" có lẽ không hề rẻ để thực hiện việc xác minh đó.
mmm

2
Các trình duyệt hiện đại cung cấp JSON.parse()triển khai gốc an toàn hơn và nhanh hơn các eval()trình phân tích cú pháp dựa trên cơ sở.
Mohammad Alhashash

15

Không phải tất cả các trình duyệt đều hỗ trợ JSON gốc, vì vậy sẽ có lúc bạn cần sử dụng eval() đến chuỗi JSON. Sử dụng trình phân tích cú pháp JSON từ http://json.org để xử lý mọi thứ dễ dàng hơn cho bạn.

Eval() là một cái ác nhưng đối với một số trình duyệt, nó là một cái ác cần thiết nhưng bạn có thể tránh nó ở đâu, hãy làm như vậy !!!!!


12

Có sự khác biệt giữa những gì JSON.parse () và eval () sẽ chấp nhận. Hãy thử đánh giá về điều này:

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

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

Hãy xem ví dụ này .


1
eval không hoạt động vì nó phân tích cú pháp chuỗi dưới dạng câu lệnh mã và do đó, coi "{...}" là một biểu thức mã thay vì một biểu thức khai báo giá trị. nếu bạn loại bỏ sự không rõ ràng (ví dụ: "[{....}]"), không có nghi ngờ gì về bản chất của biểu thức và eval sẽ tạo ra một mảng chứa đối tượng được phân tích cú pháp
Charles HETIER 25/11/14

1
Đúng. Theo truyền thống, x sẽ được bao bọc bởi dấu ngoặc đơn: eval ("(" + x + ")"). Những gì tôi đã nói vẫn còn nguyên: không có sự mơ hồ khi sử dụng JSON.parse ().
Jeff Lowery

9

Nếu bạn phân tích cú pháp JSON eval, bạn đang cho phép chuỗi được phân tích cú pháp chứa hoàn toàn bất kỳ thứ gì, vì vậy thay vì chỉ là một tập dữ liệu, bạn có thể thấy mình đang thực hiện các lệnh gọi hàm hoặc bất cứ điều gì.

Ngoài ra, JSON's parsechấp nhận một tham số bổ sung, trình phục hồi, cho phép bạn chỉ định cách xử lý các giá trị nhất định, chẳng hạn như lịch ngày (thêm thông tin và ví dụ trong tài liệu nội tuyến tại đây )


4

JSON chỉ là một tập con của JavaScript. Nhưng evalđánh giá ngôn ngữ JavaScript đầy đủ chứ không chỉ tập hợp con đó là JSON.


Đúng vậy, tôi biết điều đó. Bạn có ngụ ý rằng JSON.parse () CHỈ đánh giá JSON và không thành công trên tất cả các dữ liệu đến khác không? Hay nó chỉ đơn giản là một trình bao bọc cho: var myObject = eval ('(' + responseText + ')'); ??
Kevin Major

6
@Kevin Major: Có, phần mềm được triển khai nguyên bản JSON.parse(được triển khai trực tiếp vào công cụ JavaScript) chỉ phân tích cú pháp JSON. Nhưng việc sử dụng triển khai không phải nguyên bản khác thực hiện một số kiểm tra sự tỉnh táo và sau đó sử dụng evalvì lý do hiệu suất.
Gumbo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.