Питання Що таке JSONP?


Я розумію JSON, але не JSONP. Документ Вікіпедії на JSON є (був) найпопулярнішим результатом пошуку для JSONP. Це говорить про це:

JSONP або "JSON with padding" є розширенням JSON, в якому префікс визначається як вхідний аргумент самого виклику.

Ага? Що зателефонувати? Це не має сенсу для мене. JSON - це формат даних. Там немає дзвінка.

The Другий результат пошуку це з якогось хлопця Ремі, який пише це про JSONP:

JSONP - це ін'єкційний тег сценарію, який передає відповідь від сервера на вказану користувачем функцію.

Я можу зрозуміти це, але це все ще не має ніякого сенсу.


Так що таке JSONP? Чому це було створено (яку проблему вона вирішує)? І чому б я це використовувати?


Доповнення: Я щойно створив нова сторінка для JSONP на Вікіпедії; тепер він має чітке та ретельне опис JSONP, на базі якого jvenemaросійська відповідь


1835
2018-01-14 20:53


походження


Кеффман, чи можу я взяти його з тону, що виглядає вниз, що ти той, хто видалив ідеально розумні запитання від WIKIpedia? Не додаючи нічого або покращуючи його? Як це "вандалізм" задавати питання. Шиш. І так, в цей самий момент я збираюся покращити сторінку Вікіпедії, з інформацією, що надається jvenema. - Cheeso
Відмінно, якщо у вас є краща інформація, тоді додайте її. Але ви не задаєте питання на вікіпедії, ви додасте факти. - skaffman
Для запису, НЕ використовуйте JSONP, якщо ви не довіряєте серверу, на якому ви говорите, до 100%. Якщо це скомпрометуватиметься, ваша веб-сторінка буде тривіально скомпрометована. - ninjagecko
Також зауважте, що JSONP може бути викрадений якщо не правильно виконано. - Pacerier
Чому це питання позначається як дублікат, коли на питання це "дублікат" було задано 10 місяців після цей? - jvenema


Відповіді:


Це насправді не так складно ...

Скажімо, ви перебуваєте на домені example.com, і хочете зробити запит на домен example.net. Щоб це зробити, вам потрібно перейти межі домену, а не ні в більшості браузерів.

Один елемент, який обходить це обмеження, - теги <script>. Коли ви використовуєте тег сценарію, обмеження домену ігнорується, але за звичайних умов ви дійсно не можете робити Що завгодно з результатами, скрипт просто оцінюється.

Введіть JSONP. Коли ви робите ваш запит на сервер, який увімкнув JSONP, ви передасте спеціальний параметр, який трохи розповідає серверу про вашу сторінку. Таким чином, сервер може чудово завершити свою відповідь таким чином, що може обробляти ваша сторінка.

Наприклад, скажімо, сервер очікує на параметр під назвою "зворотний виклик", щоб увімкнути його можливості JSONP. Тоді ваш запит виглядатиме так:

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

Без JSONP це може повернути деякий базовий об'єкт JavaScript, наприклад:

{ foo: 'bar' }

Проте з JSONP, коли сервер отримує параметр "зворотний виклик", він згортає результат трохи по-іншому, повертаючи щось на зразок цього:

mycallback({ foo: 'bar' });

Як ви бачите, тепер він буде викликати вказаний вами спосіб. Отже, на вашій сторінці ви визначаєте функцію зворотного виклику:

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

І тепер, коли сценарій буде завантажений, він буде оцінений, і ваша функція буде виконана. Voila, міждоменні запити!

Варто також відзначити одну головну проблему з JSONP: ви втрачаєте великий контроль над запитом. Наприклад, немає "приємного" способу отримати правильні коди відмов. У результаті ви отримаєте таймери, щоб відстежувати запит тощо, що завжди є підозрілим. Пропозиція для JSONRequest це відмінне рішення для забезпечення міждоменного скриптування, збереження безпеки та забезпечення належного контролю за запитом.

Ці дні (2015), CORS це рекомендований підхід проти JSONRequest. JSONP як і раніше корисний для підтримки старих браузерів, але з урахуванням наслідків безпеки, якщо ви не маєте вибору, CORS - кращий вибір.


1796
2018-01-14 21:08



Зверніть увагу, що використання JSONP має певні наслідки для безпеки. Оскільки JSONP насправді є JavaScript, він може робити все, що може зробити ще javascript, тому вам потрібно довіряти провайдеру даних JSONP. Про це я написав у цьому блозі: erlend.oftedal.no/blog/?blogid=97 - Erlend
Чи дійсно є якісь нові аспекти безпеки в JSONP, які відсутні в тезі <script>? За допомогою тега сценарію браузер недвозначно довіряє серверу надавати нешкідливий Javascript, який браузер сліпо оцінює. чи змінює JSONP цей факт? Здається, це не так. - Cheeso
Ні, це не так. Ви довіряєте їй, щоб доставити JavaScript, те ж саме стосується JSONP. - jvenema
Варто зазначити, що можна трохи збільшити безпеку, змінюючи спосіб повернення даних. Якщо ви повернете сценарій у справжньому форматі JSON, наприклад mycallback ('{"foo": "bar"}') (зауважте, що цей параметр тепер це рядок), то ви можете самостійно проаналізувати дані, щоб "очистити" його раніше оцінюючи - jvenema
CURL - це рішення на стороні сервера, а не на стороні клієнта. Вони служать двом різним цілям. - jvenema


JSONP це дійсно простий трюк для подолання XMLHttpRequest однакова політика домену. (Як відомо, неможливо відправити AJAX (XMLHttpRequest) запит до іншого домену.)

Так - замість того, щоб використовувати XMLHttpRequest ми повинні використовувати сценарій Теги HTML, ті, що ви зазвичай використовуєте для завантаження js-файлів, для того, щоб js отримували дані з іншого домену. Звучить дивно?

Річ - виходить сценарій теги можуть бути використані в моді, схожої на XMLHttpRequest! Заціни:

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

Ви в кінцевому підсумку з a сценарій сегмент, який виглядає наступним чином після завантаження даних:

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

Однак це трохи незручно, тому що ми повинні отримати цей масив сценарій тег Так JSONP творці вирішили, що це буде працювати краще (і це є):

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

Зверніть увагу на my_callback функціонувати там? Тому, коли JSONP сервер отримує ваш запит і знаходить параметр зворотного виклику - замість того, щоб повертати масив звичайного js, він поверне це:

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

Подивіться, де прибуток: Тепер ми отримуємо автоматичний зворотний виклик (my_callback), який буде запускатися, як тільки ми отримаємо дані.
Це все, що потрібно знати JSONP: це теги зворотного виклику та скриптів.

ПРИМІТКА. Це прості приклади використання JSONP, це не серії готовності до готовності.

Базовий приклад JavaScript (простий канал в Твіттері за допомогою 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>

Основний приклад jQuery (простий поштовий канал через 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 виступає за JSON з підкладкою. (дуже слабко названа методика, оскільки воно насправді не має нічого спільного з тим, що більшість людей вважатиме "підкладкою").


640
2017-07-29 21:40



Дякуємо за опис тегу сценарію. Я не міг зрозуміти, як JSONP обійшлася політикою безпеки перехресного домену. Після пояснення я відчуваю, що невдало дурне пропустити точку ... - Eduard
Це дуже хороша додаткова відповідь на відповідь Jvenema - я не зрозумів, чому зворотний виклик був необхідний, поки ви не вказали, що дані json повинні бути доступні через елемент сценарію. - Matt
Відчуваєш себе чудово, знаючи, що тег сценарію працює як XMLHttp :-) Дякую за приємне пояснення - ravisoni
Дякую за таке чітке пояснення. Я хотів би, щоб мої коледжні підручники були написані такими людьми, як ти :) - hashbrown
Хороша експлікація, а не попередня. Звичайно, ваш виписка ", яку ви зазвичай використовуєте для завантаження js-файлів, для того, щоб js міг отримувати дані з іншого домену. Звуки дивні?" також є око для мене. Приклад коду дуже знаменитий. - SIslam


JSONP працює шляхом створення елемента "скрипта" (або в HTML-розмітці, або вставлено в DOM через JavaScript), який запитує до віддаленого розташування служби даних. Відповідь - це завантажений в ваш браузер JavaScript-файл із назвою заздалегідь визначеної функції разом із параметром, що передаються, тобто дані tht JSON запитуються. Коли виконується скрипт, ця функція викликається разом із даними JSON, що дозволяє запитній сторінці отримувати та обробляти дані.

Для подальшого читання візиту:  https://blogs.sap.com/2013/07/15/secret-behind-jsonp/

фрагмент коду клієнтської сторони

    <!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>

Серверна частина 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



посилання у верхній частині всього 404 років - Man Personson
Зміст цього посилання тепер доступний на http://scn.sap.com/community/developer-center/front-end/blog/2013/07/15/secret-behind-jsonp. - ᴠɪɴᴄᴇɴᴛ


Оскільки ви можете попросити сервер додати префікс до поверненого об'єкту JSON. Напр

function_prefix(json_object);

для того, щоб браузер eval "inline" рядок JSON як вираз. Цей трюк дає змогу серверу «вводити» код JavaScript, безпосередньо в браузері клієнта, і це, обходячи обмеження «одного джерела».

Іншими словами, ви можете мати Междоменный обмін даними.


Як правило, XMLHttpRequest не дозволяє міждоменному обміну даними безпосередньо (потрібно пройти через сервер у тому ж домені), тоді як:

<script src="some_other_domain/some_data.js&prefix=function_prefix> "можна отримати доступ до даних з іншого домену, ніж від джерела.


Також варто зауважити: хоча сервер слід вважати "довіреним", перш ніж намагатися зробити такий "трюк", може міститися побічні ефекти від можливих змін у форматі об'єктів тощо. Якщо function_prefix(наприклад, відповідна функція js) використовується для отримання об'єкта JSON, ця функція може виконувати перевірки, перш ніж приймати / подальшу обробку повернутих даних.


37
2018-01-14 20:58





JSONP - чудовий простір, щоб попередити помилки міждоменних сценаріїв. Ви можете споживати службу JSONP виключно з JS без необхідності вводити проксі AJAX на стороні сервера.

Ви можете скористатись b1t.co Служба, щоб побачити, як вона працює. Це безкоштовна служба JSONP, яка дозволяє вам зменшити URL-адреси. Ось URL, який можна використовувати для сервісу:

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

Наприклад, дзвінок http://b1t.co/Site/api/External/MakeUrlWithGet?callback=whateverJavascriptName&url=google.com

повернеться

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

І, таким чином, коли цей файл завантажується у ваш js як src, він автоматично запускає який-небудь JavascriptName, який слід реалізувати як функцію зворотного виклику:

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

Щоб насправді зробити виклик JSONP, ви можете зробити це кількома способами (у тому числі за допомогою jQuery), але це чистий JS-приклад:

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);
}

Пошаговий приклад і веб-служба jsonp для практики доступні за адресою: цей пост


17
2018-03-28 15:59



Дякуємо за повідомлення вашої відповіді! Зверніть увагу, що ви повинні опублікувати основні частини відповіді тут, на цьому сайті, або ваші публікації ризикує бути видаленими Дивіться розділ "Поширені запитання", де згадуються відповіді, що є "трохи більше, ніж посиланням". Ви можете включити посилання, якщо хочете, але тільки як "посилання". Відповідь має стояти самостійно, не потребуючи посилання. - Taryn♦


Простий приклад використання 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





Перш ніж розуміти JSONP, вам слід знати формат JSON та XML. В даний час найбільш часто використовуваний формат даних в Інтернеті є XML, але XML дуже складний. Це робить користувачів незручним обробляти вбудовані веб-сторінки.

Щоб зробити JavaScript легко обмінюватися даними, навіть як програма обробки даних, ми використовуємо формулювання відповідно до об'єктів JavaScript і розробляємо простий формат обміну даними, який є JSON. JSON може використовуватися як дані, або як програма JavaScript.

JSON можна безпосередньо вбудовувати в JavaScript, за допомогою них ви можете безпосередньо виконувати певну програму JSON, але через обмеження безпеки механізм Google Sandbox блокує виконання міждоменного коду JSON.

Щоб JSON можна було передавати після виконання, ми розробили JSONP. JSONP обходить обмеження безпеки браузера з функцією зворотного виклику JavaScript і тегом <script>.

Отже, коротко, це пояснює, що таке JSONP, яку проблему вона вирішує (коли її використовувати).


9
2017-12-08 04:02



Я спростував це тому, що я не вірю в твердження, що XML був найпопулярнішим у форматі DAT в Інтернеті в грудні 15 грудня. - RobbyD