Câu hỏi JSONP là gì?


Tôi hiểu JSON, nhưng không hiểu JSONP. Tài liệu của Wikipedia về JSON là (là) kết quả tìm kiếm hàng đầu cho JSONP. Nó nói điều này:

JSONP hoặc "JSON có đệm" là một phần mở rộng JSON trong đó tiền tố được chỉ định làm đối số đầu vào của cuộc gọi.

Huh? Gọi gì? Điều đó không có ý nghĩa với tôi. JSON là một định dạng dữ liệu. Không có cuộc gọi.

Các Kết quả tìm kiếm thứ hai là từ một anh chàng tên là Remy, người viết về JSONP:

JSONP là tiêm thẻ script, chuyển trả lời từ máy chủ đến một hàm do người dùng chỉ định.

Tôi có thể hiểu được điều đó, nhưng nó vẫn không có ý nghĩa gì cả.


Vậy JSONP là gì? Tại sao nó được tạo ra (nó giải quyết vấn đề gì)? Và tại sao tôi lại sử dụng nó?


Phụ lục: Tôi vừa mới tạo một trang mới cho JSONP trên Wikipedia; nó bây giờ có một mô tả rõ ràng và kỹ lưỡng về JSONP, dựa trên jvenemacâu trả lời.


1835
2018-01-14 20:53


gốc


Skaffman, tôi có nhận nó sau đó từ giai điệu nhìn xuống mũi của bạn rằng bạn là người đã loại bỏ những câu hỏi hoàn hảo hợp lý từ WIKIpedia? Mà không cần thêm bất cứ điều gì hoặc cải thiện nó? Làm thế nào là nó "phá hoại" để đặt một câu hỏi. Sheesh. Và vâng, tại thời điểm này tôi sẽ cải thiện trang wikipedia, với thông tin mà jvenema cung cấp. - Cheeso
Tuyệt vời, nếu bạn có thông tin tốt hơn, hãy thêm nó. Nhưng bạn không đặt câu hỏi trên wikipedia, bạn thêm sự kiện. - skaffman
Đối với bản ghi, KHÔNG sử dụng JSONP nếu bạn không tin cậy máy chủ mà bạn đang nói đến 100%. Nếu nó bị xâm nhập, trang web của bạn sẽ bị xâm phạm một cách đáng kể. - ninjagecko
Cũng lưu ý rằng JSONP có thể bị tấn công nếu không được triển khai đúng. - Pacerier
Tại sao câu hỏi này được gắn thẻ là trùng lặp khi câu hỏi này là "trùng lặp" được hỏi 10 tháng sau cái này? - jvenema


Các câu trả lời:


Nó thực sự không quá phức tạp ...

Giả sử bạn đang ở trên miền example.com và bạn muốn thực hiện yêu cầu cho miền example.net. Để làm như vậy, bạn cần phải vượt qua ranh giới miền, một không-không có trong hầu hết các trình duyệt.

Một mục vượt qua giới hạn này là các thẻ <script>. Khi bạn sử dụng thẻ tập lệnh, giới hạn miền bị bỏ qua, nhưng trong các trường hợp bình thường, bạn không thể thực sự làm bất cứ điều gì với kết quả, kịch bản chỉ được đánh giá.

Nhập JSONP. Khi bạn yêu cầu một máy chủ được bật JSONP, bạn chuyển một tham số đặc biệt cho máy chủ biết một chút về trang của bạn. Bằng cách đó, máy chủ có thể gói gọn phản ứng của nó theo cách mà trang của bạn có thể xử lý.

Ví dụ, giả sử máy chủ mong đợi một tham số được gọi là "callback" để kích hoạt các khả năng JSONP của nó. Sau đó, yêu cầu của bạn sẽ như sau:

http://www.example.net/sample.aspx?callback=mycallback

Không có JSONP, điều này có thể trả về một số đối tượng JavaScript cơ bản, như sau:

{ foo: 'bar' }

Tuy nhiên, với JSONP, khi máy chủ nhận được tham số "gọi lại", nó kết thúc tốt đẹp kết quả một chút khác, trả về một cái gì đó như thế này:

mycallback({ foo: 'bar' });

Như bạn có thể thấy, nó sẽ gọi phương thức mà bạn đã chỉ định. Vì vậy, trong trang của bạn, bạn xác định hàm gọi lại:

mycallback = function(data){
  alert(data.foo);
};

Và bây giờ, khi kịch bản được tải, nó sẽ được đánh giá và chức năng của bạn sẽ được thực hiện. Thì đấy, yêu cầu miền chéo!

Nó cũng đáng chú ý một vấn đề lớn với JSONP: bạn mất rất nhiều quyền kiểm soát yêu cầu. Ví dụ, không có cách "đẹp" để lấy lại mã lỗi đúng. Kết quả là, bạn kết thúc bằng cách sử dụng bộ đếm thời gian để theo dõi yêu cầu, vv, mà luôn luôn là một chút nghi ngờ. Đề xuất cho JSONRequest là một giải pháp tuyệt vời để cho phép tạo kịch bản miền chéo, duy trì bảo mật và cho phép kiểm soát đúng yêu cầu.

Những ngày này (2015), CORS là phương pháp được đề xuất so với JSONRequest. JSONP vẫn hữu ích cho hỗ trợ trình duyệt cũ hơn, nhưng với các tác động bảo mật, trừ khi bạn không có CORS nào là lựa chọn tốt hơn.


1796
2018-01-14 21:08



Xin lưu ý rằng việc sử dụng JSONP có một số tác động bảo mật. Vì JSONP thực sự là javascript, nó có thể làm mọi thứ khác mà javascript có thể làm, vì vậy bạn cần tin tưởng nhà cung cấp dữ liệu JSONP. Tôi đã viết một bài đăng trên blog về nó ở đây: erlend.oftedal.no/blog/?blogid=97 - Erlend
Có thực sự bất kỳ ý nghĩa bảo mật mới nào trong JSONP không có trong thẻ <script> không? Với một thẻ script, trình duyệt hoàn toàn tin tưởng vào máy chủ để cung cấp Javascript không độc hại mà trình duyệt đánh giá một cách mù quáng. sao JSONP thay đổi thực tế đó? Có vẻ như nó không. - Cheeso
Không, nó không. Bạn tin tưởng nó để cung cấp javascript, cùng một điều áp dụng cho JSONP. - jvenema
Cần lưu ý rằng bạn có thể tăng cường bảo mật một chút bằng cách thay đổi cách dữ liệu được trả về. Nếu bạn trả về kịch bản ở định dạng JSON đúng như mycallback ('{"foo": "bar"}') (lưu ý rằng tham số bây giờ là một chuỗi), sau đó bạn có thể phân tích cú pháp dữ liệu theo cách thủ công để "làm sạch" trước đánh giá. - jvenema
CURL là một giải pháp phía máy chủ, không phải là phía máy khách. Họ phục vụ hai mục đích khác nhau. - jvenema


JSONP thực sự là một mẹo đơn giản để vượt qua XMLHttpRequest chính sách miền giống nhau. (Như bạn biết một người không thể gửi AJAX (XMLHttpRequest) yêu cầu đến một tên miền khác.)

Vì vậy - thay vì sử dụng XMLHttpRequest chúng ta phải sử dụng kịch bản Các thẻ HTML, những thẻ bạn thường sử dụng để tải các tệp js, để các js lấy dữ liệu từ một miền khác. Âm thanh lạ?

Thing là - hóa ra kịch bản thẻ có thể được sử dụng trong một thời trang tương tự như XMLHttpRequest! Kiểm tra điều này:

script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data';

Bạn sẽ kết thúc với một kịch bản phân đoạn trông giống như sau khi tải dữ liệu:

<script>
{['some string 1', 'some data', 'whatever data']}
</script>

Tuy nhiên đây là một chút bất tiện, bởi vì chúng ta phải lấy mảng này từ kịch bản nhãn. Vì thế JSONP người sáng tạo đã quyết định rằng điều này sẽ hoạt động tốt hơn (và đó là):

script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data? callback = my_callback';

Lưu ý my_callback chức năng ở đó? Vậy - khi nào JSONP server nhận được yêu cầu của bạn và tìm tham số gọi lại - thay vì trả về mảng js đơn giản, nó sẽ trả về điều này:

my_callback({['some string 1', 'some data', 'whatever data']});

Xem lợi nhuận ở đâu: bây giờ chúng tôi nhận được gọi lại tự động (my_callback) sẽ được kích hoạt khi chúng tôi nhận được dữ liệu.
Đó là tất cả những gì cần biết về JSONP: đó là một thẻ gọi lại và tập lệnh.

LƯU Ý: đây là những ví dụ đơn giản về cách sử dụng JSONP, đây không phải là các kịch bản sẵn sàng sản xuất.

Ví dụ JavaScript cơ bản (nguồn cấp dữ liệu Twitter đơn giản sử dụng JSONP)

<html>
    <head>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
        <script>
        function myCallback(dataWeGotViaJsonp){
            var text = '';
            var len = dataWeGotViaJsonp.length;
            for(var i=0;i<len;i++){
                twitterEntry = dataWeGotViaJsonp[i];
                text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
            }
            document.getElementById('twitterFeed').innerHTML = text;
        }
        </script>
        <script type="text/javascript" src="http://twitter.com/status/user_timeline/padraicb.json?count=10&callback=myCallback"></script>
    </body>
</html>

Ví dụ jQuery cơ bản (nguồn cấp dữ liệu Twitter đơn giản sử dụng JSONP)

<html>
    <head>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script>
            $(document).ready(function(){
                $.ajax({
                    url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10',
                    dataType: 'jsonp',
                    success: function(dataWeGotViaJsonp){
                        var text = '';
                        var len = dataWeGotViaJsonp.length;
                        for(var i=0;i<len;i++){
                            twitterEntry = dataWeGotViaJsonp[i];
                            text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
                        }
                        $('#twitterFeed').html(text);
                    }
                });
            })
        </script>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
    </body>
</html>


JSONP viết tắt của JSON có đệm. (kỹ thuật có tên rất kém vì nó thực sự không liên quan gì đến phần lớn mọi người sẽ nghĩ đến là "đệm").


640
2017-07-29 21:40



Cảm ơn lời giải thích thẻ script. Tôi đã không thể tìm ra cách chính sách bảo mật miền chéo bị bỏ qua bởi JSONP. Sau lời giải thích, tôi cảm thấy một kẻ ngu ngốc bỏ lỡ điểm ... - Eduard
Đây là một câu trả lời bổ sung rất tốt cho câu trả lời của jvenema - Tôi không hiểu tại sao gọi lại là cần thiết cho đến khi bạn chỉ ra rằng dữ liệu json sẽ phải được truy cập thông qua phần tử script. - Matt
Cảm thấy tuyệt vời sau khi biết rằng thẻ Script làm việc như XMLHttp :-) Cảm ơn lời giải thích tốt đẹp - ravisoni
Cảm ơn lời giải thích rõ ràng như vậy. Tôi muốn sách giáo khoa đại học của tôi được viết bởi những người như bạn :) - hashbrown
Giải thích tốt hơn là trước đó. Ofcourse- đoạn trích của bạn "những người bạn thường sử dụng để tải các tập tin js, để cho js để có được dữ liệu từ một tên miền khác. Âm thanh lạ?" cũng là mở mắt cho tôi. Ví dụ mã trong rất nhiều lừng lẫy. - SIslam


JSONP hoạt động bằng cách xây dựng một phần tử "script" (trong đánh dấu HTML hoặc được chèn vào DOM thông qua JavaScript), yêu cầu đến một vị trí dịch vụ dữ liệu từ xa. Phản hồi là một javascript được nạp vào trình duyệt của bạn với tên của hàm được định nghĩa trước cùng với tham số đang được truyền, đó là dữ liệu JSON được yêu cầu. Khi kịch bản thực hiện, hàm được gọi cùng với dữ liệu JSON, cho phép trang yêu cầu nhận và xử lý dữ liệu.

Để đọc thêm:  https://blogs.sap.com/2013/07/15/secret-behind-jsonp/

đoạn mã phía máy khách

    <!DOCTYPE html>
    <html lang="en">
    <head>
     <title>AvLabz - CORS : The Secrets Behind JSONP </title>
     <meta charset="UTF-8" />
    </head>
    <body>
      <input type="text" id="username" placeholder="Enter Your Name"/>
      <button type="submit" onclick="sendRequest()"> Send Request to Server </button>
    <script>
    "use strict";
    //Construct the script tag at Runtime
    function requestServerCall(url) {
      var head = document.head;
      var script = document.createElement("script");

      script.setAttribute("src", url);
      head.appendChild(script);
      head.removeChild(script);
    }

    //Predefined callback function    
    function jsonpCallback(data) {
      alert(data.message); // Response data from the server
    }

    //Reference to the input field
    var username = document.getElementById("username");

    //Send Request to Server
    function sendRequest() {
      // Edit with your Web Service URL
      requestServerCall("http://localhost/PHP_Series/CORS/myService.php?callback=jsonpCallback&message="+username.value+"");
    }    

  </script>
   </body>
   </html>

Mã phía máy chủ của mã PHP

<?php
    header("Content-Type: application/javascript");
    $callback = $_GET["callback"];
    $message = $_GET["message"]." you got a response from server yipeee!!!";
    $jsonResponse = "{\"message\":\"" . $message . "\"}";
    echo $callback . "(" . $jsonResponse . ")";
?>

38
2018-03-17 13:32



liên kết ở trên cùng chỉ 404 ngay bây giờ - Man Personson
Nội dung của liên kết đó hiện có sẵn tại http://scn.sap.com/community/developer-center/front-end/blog/2013/07/15/secret-behind-jsonp. - ᴠɪɴᴄᴇɴᴛ


Vì bạn có thể yêu cầu máy chủ gắn thêm tiền tố vào đối tượng JSON được trả về. Ví dụ

function_prefix(json_object);

để trình duyệt eval "inline" chuỗi JSON dưới dạng một biểu thức. Thủ thuật này làm cho máy chủ có thể "tiêm" mã javascript trực tiếp trong trình duyệt Máy khách và điều này với việc bỏ qua các hạn chế "cùng nguồn gốc".

Nói cách khác, bạn có thể có trao đổi dữ liệu giữa nhiều miền.


Thông thường, XMLHttpRequest không cho phép trao đổi dữ liệu tên miền chéo trực tiếp (cần phải đi qua một máy chủ trong cùng một tên miền) trong khi:

<script src="some_other_domain/some_data.js&prefix=function_prefix> `một người có thể truy cập dữ liệu từ một tên miền khác với nguồn gốc.


Cũng đáng chú ý: mặc dù máy chủ nên được coi là "đáng tin cậy" trước khi cố gắng loại "lừa", các tác dụng phụ của sự thay đổi có thể trong định dạng đối tượng, vv có thể được chứa. Nếu một function_prefix(tức là một hàm js thích hợp) được sử dụng để nhận đối tượng JSON, hàm nói trên có thể thực hiện kiểm tra trước khi chấp nhận / tiếp tục xử lý dữ liệu trả về.


37
2018-01-14 20:58





JSONP là một cách tuyệt vời để tránh các lỗi tập lệnh đa miền. Bạn có thể sử dụng một dịch vụ JSONP hoàn toàn với JS mà không cần phải thực hiện một proxy AJAX ở phía máy chủ.

Bạn có thể dùng b1t.co dịch vụ để xem nó hoạt động như thế nào. Đây là một dịch vụ JSONP miễn phí cho phép bạn rút gọn các URL của mình. Đây là url để sử dụng cho dịch vụ:

http://b1t.co/Site/api/External/MakeUrlWithGet?callback=[resultsCallBack]&url=[escapedUrlToMinify]

Ví dụ như cuộc gọi, http://b1t.co/Site/api/External/MakeUrlWithGet?callback=whateverJavascriptName&url=google.com

sẽ trở lại

whateverJavascriptName({"success":true,"url":"http://google.com","shortUrl":"http://b1t.co/54"});

Và do đó khi nhận được tải trong js của bạn như là một src, nó sẽ tự động chạy bất cứ điều gìJavascriptName mà bạn nên thực hiện như chức năng gọi lại của bạn:

function minifyResultsCallBack(data)
{
    document.getElementById("results").innerHTML = JSON.stringify(data);
}

Để thực sự thực hiện cuộc gọi JSONP, bạn có thể thực hiện theo một số cách (bao gồm sử dụng jQuery) nhưng đây là một ví dụ JS thuần túy:

function minify(urlToMinify)
{
   url = escape(urlToMinify);
   var s = document.createElement('script');
   s.id = 'dynScript';
   s.type='text/javascript';
   s.src = "http://b1t.co/Site/api/External/MakeUrlWithGet?callback=resultsCallBack&url=" + url;
   document.getElementsByTagName('head')[0].appendChild(s);
}

Một ví dụ từng bước và một dịch vụ web jsonp để thực hành có sẵn tại: bài này


17
2018-03-28 15:59



Cảm ơn bạn đã đăng câu trả lời! Xin lưu ý rằng bạn nên đăng các phần thiết yếu của câu trả lời ở đây, trên trang web này hoặc các nguy cơ của bạn trong bài đăng sẽ bị xóa Xem Câu hỏi thường gặp nơi đề cập đến câu trả lời 'hầu như không phải là liên kết'. Bạn vẫn có thể bao gồm liên kết nếu bạn muốn, nhưng chỉ là 'tham chiếu'. Câu trả lời nên tự đứng lên mà không cần liên kết. - Taryn♦


Một ví dụ đơn giản cho việc sử dụng JSONP.

client.html

    <html>
    <head>
   </head>
     body>


    <input type="button" id="001" onclick=gO("getCompany") value="Company"  />
    <input type="button" id="002" onclick=gO("getPosition") value="Position"/>
    <h3>
    <div id="101">

    </div>
    </h3>

    <script type="text/javascript">

    var elem=document.getElementById("101");

    function gO(callback){

    script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'http://localhost/test/server.php?callback='+callback;
    elem.appendChild(script);
    elem.removeChild(script);


    }

    function getCompany(data){

    var message="The company you work for is "+data.company +"<img src='"+data.image+"'/   >";
    elem.innerHTML=message;
}

    function getPosition(data){
    var message="The position you are offered is "+data.position;
    elem.innerHTML=message;
    }
    </script>
    </body>
    </html>

server.php

  <?php

    $callback=$_GET["callback"];
    echo $callback;

    if($callback=='getCompany')
    $response="({\"company\":\"Google\",\"image\":\"xyz.jpg\"})";

    else
    $response="({\"position\":\"Development Intern\"})";
    echo $response;

    ?>    

10
2018-06-06 06:45





Trước khi hiểu JSONP, bạn cần biết định dạng JSON và XML. Hiện tại, định dạng dữ liệu được sử dụng thường xuyên nhất trên web là XML, nhưng XML rất phức tạp. Nó làm cho người dùng bất tiện để xử lý nhúng trong các trang Web.

Để làm cho JavaScript có thể dễ dàng trao đổi dữ liệu, ngay cả khi chương trình xử lý dữ liệu, chúng tôi sử dụng từ ngữ theo các đối tượng JavaScript và phát triển một định dạng trao đổi dữ liệu đơn giản, là JSON. JSON có thể được sử dụng làm dữ liệu hoặc dưới dạng chương trình JavaScript.

JSON có thể được nhúng trực tiếp trong JavaScript, sử dụng chúng, bạn có thể trực tiếp thực thi một số chương trình JSON nhất định, nhưng do các ràng buộc về bảo mật, cơ chế Sandbox của trình duyệt vô hiệu hóa thực thi mã JSON giữa nhiều miền.

Để làm cho JSON có thể được chuyển sau khi thực hiện, chúng tôi đã phát triển JSONP. JSONP bỏ qua các giới hạn bảo mật của trình duyệt bằng chức năng gọi lại JavaScript và thẻ <script>.

Vì vậy, trong ngắn hạn nó giải thích những gì JSONP là, vấn đề gì nó giải quyết (khi sử dụng nó).


9
2017-12-08 04:02



Tôi đã bỏ phiếu này vì tôi không tin rằng tuyên bố rằng XML là định dạng dat được sử dụng nhiều nhất trên web vào tháng 12 '15. - RobbyD