2012-04-17 29 views
17

Tôi gặp sự cố khi hiểu chi tiết về cách hoạt động của yêu cầu jsonp. Tôi đã đọc một số nguồn bao gồm cả wiki trên jsonp và vẫn còn rất bối rối về cách gọi lại thực sự được một tổ chức của chức năng trả về từ máy chủ khi một cuộc gọi jsonp được thực hiện. Ví dụ: trong wiki, nguồn của yêu cầu được đặt là:Bối rối về cách yêu cầu JSONP hoạt động

src="http://server2.example.com/RetrieveUser?UserId=1234&jsonp=parseResponse" 

Chính xác jsonp = parseResponse thực sự có ý nghĩa gì? Sau đó, họ tiếp tục nói rằng trọng tải là:

parseResponse({"Name": "Foo", "Id" : 1234, "Rank": 7}); 

Tính năng này hoạt động như thế nào? Tôi bối rối về toàn bộ chức năng gọi lại. Tên hàm parseResponse được truyền cho máy chủ và bằng cách nào đó dữ liệu được trả về trở thành các tham số cho hàm này? Ai đó có thể vui lòng giải thích rõ chính xác cách dữ liệu được truy xuất/sử dụng từ yêu cầu jsonp không?

+0

có thể trùng lặp [Vui lòng giải thích JSONP] (http://stackoverflow.com/questions/2067472/please-explain-jsonp) – Jon

Trả lời

40

Việc gọi lại là một chức năng BẠN 'VE được định nghĩa trong mã của riêng bạn. Máy chủ jsonp sẽ bọc trả lời của nó bằng một cuộc gọi hàm có tên giống như hàm gọi lại được chỉ định của bạn.

gì xảy ra nó này:

1) Mã của bạn tạo ra các yêu cầu JSONP, mà kết quả trong một <script> khối mới trông như thế này:

<script src="http://server2.example.com/RetrieveUser?UserId=1234&jsonp=parseResponse"></script> 

2) Đó thẻ script mới được thực hiện bởi trình duyệt của bạn, dẫn đến yêu cầu đến máy chủ JSONP.Nó phản ứng với

parseResponse({"Name": "Foo", "Id" : 1234, "Rank": 7}); 

3) Kể từ khi yêu cầu này xuất phát từ một thẻ script, nó khá nhiều CHÍNH XÁC giống như nếu bạn muốn theo nghĩa đen đặt

<script> 
    parseResponse({"Name": "Foo", "Id" : 1234, "Rank": 7}); 
</script> 

vào trang của bạn. Bây giờ tập lệnh mới này đã được tải từ máy chủ từ xa, tập lệnh này sẽ được thực thi và điều duy nhất nó sẽ thực hiện là gọi hàm, parseResponse(), chuyển dữ liệu JSON làm tham số duy nhất của cuộc gọi chức năng .

Vì vậy, ở một nơi khác trong mã của bạn, bạn phải:

function parseResponse(data) { 
    alert(data.Name); // outputs 'Foo' 
} 

Về cơ bản, JSONP là một cách để bỏ qua chính sách bảo mật kịch bản cùng nguồn gốc của trình duyệt, bằng việc có một máy chủ của bên thứ 3 tiêm một cuộc gọi chức năng trực tiếp vào trang của bạn. Lưu ý rằng điều này là do thiết kế rất không an toàn. Bạn đang phụ thuộc vào dịch vụ từ xa là đáng kính và không có ý định độc hại. Không có gì ngăn cản một dịch vụ xấu từ trả lại một số mã JS đánh cắp ngân hàng/facebook của bạn/bất kỳ thông tin đăng nhập nào. ví dụ: phản hồi JSONP có thể là

internalUseOnlyFunction('deleteHarddrive'); 

thay vì parseReponse (...). Nếu trang web từ xa biết cấu trúc mã của bạn, nó có thể thực hiện các hoạt động tùy ý với mã đó, bởi vì bạn đã mở cửa trước mở rộng để cho phép trang web đó làm bất cứ điều gì nó muốn.

+8

Tôi sẽ không đi xa như một ví dụ như 'deleteHardDrive' (javascript không thể làm điều đó từ trình duyệt) nhưng nó chắc chắn đáng chú ý rằng điều này có thể nguy hiểm. – hitautodestruct

+1

Giải thích tuyệt vời! – FloatingRock

1

Chỉnh sửa: Như Jon đã nói, có cách giải thích tốt hơn cho nó here.

JSONP sử dụng thẻ tập lệnh để thực hiện các yêu cầu gốc chéo. Vì thẻ tập lệnh được sử dụng để bao gồm tập lệnh, máy chủ cần trả lại JavaScript hợp lệ. Cách chúng tôi cung cấp JavaScript cho khách hàng là thông qua một cuộc gọi hàm. Bạn cho máy chủ biết chức năng nào bạn muốn tập lệnh gọi và sau đó bạn tạo hàm đó cục bộ. Khi kịch bản được tải xong, hàm của bạn sẽ được gọi với dữ liệu dưới dạng tham số.

Vì vậy, nếu bạn đã làm một yêu cầu JSONP tại URL mà bạn đề cập, và nó trở lại payload bạn đề cập, bạn sẽ nhận được dữ liệu của bạn bằng cách làm này:

function parseResponse(data) { 
    console.log("JSONP request complete", data); 
} 
+0

Dữ liệu được trả về kỳ diệu trở thành thông số cho hàm parseRepsonse như thế nào? –

+0

@JohnBaum vì máy chủ tạo mã JS sẽ được gọi? –

0

Các tên hàm parseResponse được truyền đến máy chủ và bằng cách nào đó dữ liệu trả về sẽ trở thành tham số cho hàm này

Hình như bạn chỉ cần giải thích điều đó cho mình, jsonp=parseResponse là cách ứng dụng điều này đặt ra chức năng gọi lại, vì vậy nó trả về một func tion với dữ liệu json của bạn trong nó, trông giống như

parseResponse({"Name": "Foo", "Id" : 1234, "Rank": 7}); 

được gọi là khi nó được nạp và sẽ được xử lý bởi một hàm trong JS của bạn như:

function parseResponse(data){ 
    console.log(data); 
} 
Các vấn đề liên quan