2009-12-03 26 views
83

Spider Sense của tôi cảnh báo 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 nếu JSON.parse() - mà tôi giả định là một phần của JavaScript và không phải là một chức năng cụ thể của trình duyệt - là an toàn hơn.JSON.parse vs. eval()

Trả lời

97

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

+0

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

+2

Xin lỗi, Matheus, tôi phải đồng ý. Vấn đề là khi bạn đang sử dụng eval() để giải thích "đầu vào của người dùng" - đó là bất kỳ nguồn bên ngoài nào 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 vì dữ liệu không được xác định đượ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 qua cuộc gọi kiểu AJAX. Bạn vẫn có thể cần xác nhận các trường riêng lẻ để tránh các cuộc tấn công "nhầm lẫn", nhưng sử dụng JSON.parse là một bước đầu tiên tốt. – JackLThornton

+0

@Hydro Ngắn bằng chứng về khái niệm: thử 'eval ('alert (1)');'. –

4

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

+0

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

+5

@Kevin Major: Vâng, thực thi nguyên gốc 'JSON.parse' (được triển khai trực tiếp vào JavaScript engine) chỉ phân tích cú pháp JSON. Nhưng các triển khai không thực hiện khác sử dụng một số kiểm tra sanity và sau đó sử dụng 'eval' cho các lý do hiệu suất. – Gumbo

9

Nếu bạn phân tích cú pháp JSON bằng eval, bạn 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 hợp dữ liệu, bạn có thể tự mình thực hiện các cuộc gọi hàm hoặc bất kỳ điều gì.

Ngoài ra, JSON của parse chấp nhận một tham số aditional, người làm phấn khởi, cho phép bạn chỉ định làm thế nào để đối phó với giá trị nhất định, chẳng hạn như datetimes (thêm thông tin và ví dụ trong tài liệu inline here)

13

Không phải tất cả các trình duyệt đều có hỗ trợ JSON gốc do đó sẽ có những lúc bạn cần sử dụng eval() cho 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 điều ác nhưng đối với một số trình duyệt, đó là điều ác cần thiết nhưng bạn có thể tránh điều đó, hãy làm như vậy !!!!!

29

Tất cả JSON.parse triển khai rất có thể sử dụng eval()

JSON.parse được dựa trên Douglas Crockford's solution, trong đó sử dụng eval() ngay trên line 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 + ')'); 

Lợi thế của JSON.parse là nó xác minh đối số là cú pháp JSON chính xác.

+50

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

+3

Tôi đã thử nghiệm 'JSON.parse()' trong Firefox 28 và Chromium 33 trên hệ thống Linux Mint của tôi. Nó nhanh gấp 2 lần so với 'eval()' trong Firefox và 4x nhanh như 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 với mã nguồn của trình duyệt của tôi. – jbo5112

+0

@plodder "lợi thế" có lẽ không phải là rẻ để làm điều đó xác minh. – momomo

9

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

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

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

Xem example này.

+1

eval không hoạt động vì nó phân tích cú pháp các chuỗi như là các câu lệnh mã và do đó, xem xét "{...}" như 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ự mơ hồ ("[{....}]" ví dụ), không có nghi ngờ về bản chất của biểu thức và eval sẽ tạo ra một mảng chứa objet được phân tích cú pháp –

+1

Có. Theo truyền thống, x sẽ được bao quanh bởi dấu ngoặc đơn: eval ("(" + x + ")"). Những gì tôi nói vẫn là viết tắt: không có sự mơ hồ khi sử dụng JSON.parse(). –