TL; DR
JSONP - это старый трюк , изобретенный, чтобы обойти ограничение безопасности, которое запрещает нам получать данные JSON, которые находятся на другом веб-сайте (другой оригинал <5472887357353 ), чем тот, в котором мы находимся.
Уловка работает с использованием тега <script>
, который запрашивает JSON из этого места, например: { "user":"Smith" }
, но заключен в функцию, фактический JSONP («JSON с заполнением») :
peopleDataJSONP({"user":"Smith"})
Получение его в этой форме позволяет нам использовать данные в нашей функции peopleDataJSONP
. JSONP - плохая практика и больше не нужен, не используйте его (читайте ниже).
Проблема
Допустим, мы хотим использовать на ourweb.com
некоторые данные JSON (или любые необработанные данные), размещенные на anotherweb.com
. Если бы мы использовали запрос GET (подумайте XMLHttpRequest
или fetch
вызов, $.ajax
и т. Д.), Наш браузер сообщит нам, что это не разрешено с этой уродливой ошибкой:
Как получить нужные данные? Что ж, теги <script>
не подлежат ограничению всего сервера (origin 1 )! Вот почему мы можем загрузить библиотеку, такую как jQuery или Google Maps, с любого сервера, например CDN, без каких-либо ошибок.
Вот важный момент: если задуматься, эти библиотеки являются актуальным исполняемым кодом JS (обычно это массивная функция со всей логикой внутри). Но необработанные данные? Данные JSON не являются кодом . Бежать нечего; это просто текст.
Следовательно, у нас нет возможности обрабатывать или манипулировать нашими ценными данными. Браузер загрузит данные, на которые указывает наш тег <script>
, и при обработке он законно пожалуется:
черт возьми, это {"user":"Smith"}
чушь, которую мы загрузили? Это не код. Я не могу вычислить, синтаксическая ошибка!
Взлом JSONP
Старый / хитрый способ использовать эти данные? Если бы мы могли каким-то образом сделать простой текст исполняемым , мы могли бы получить его во время выполнения. Итак, нам нужен anotherweb.com
, чтобы отправить его с некоторой логикой, чтобы при загрузке ваш код в браузере мог использовать указанные данные. Нам нужны две вещи: 1) , чтобы получить данные таким образом, чтобы их можно было запустить, и 2) написать некоторый код в клиенте, чтобы при запуске данных этот код вызывается, и мы можем использовать данные.
Для 1) мы просим внешний сервер отправить нам данные JSON внутри функции JS. Сами данные настраиваются как вход этой функции. Это выглядит так:
peopleDataJSONP({"user":"Smith"})
, что делает его кодом JS , наш браузер будет анализировать и запускать без жалоб! Точно так же, как с библиотекой jQuery.
Чтобы получить такие данные, клиент «запрашивает» их у JSONP-дружественного сервера, обычно это делается следующим образом:
<script src="https://anotherweb.com/api/data-from-people.json?myCallback=peopleDataJSONP"></script>
Согласно 2) , поскольку наш браузер получит JSONP с этим именем функции, нам нужна функция с таким же именем в нашем коде, например:
function peopleDataJSONP(data){
alert(data.user); // "Smith"
}
Браузер загрузит JSONP и запустит его, , который вызывает нашу функцию , где аргумент data
будет данными JSON из anotherweb.com
. Теперь мы можем делать с нашими данными все, что захотим.
Не используйте JSONP, используйте CORS
JSONP - это межсайтовый взлом с несколькими недостатками:
- Мы можем выполнять только запросы GET
- Поскольку это запрос GET, запускаемый простым тегом скрипта, мы не получаем полезных ошибок или информации о ходе выполнения
- Есть также некоторые проблемы с безопасностью, такие как запуск в вашем клиентском JS-коде, который может быть изменен на вредоносную полезную нагрузку
- Он решает проблему только с данными JSON, но политика безопасности Same-Origin применяется к другим данным (веб-шрифты, изображения / видео, нарисованные с помощью drawImage () ...)
- Это не очень элегантно и не читается.
Вывод состоит в том, что нет необходимости использовать его в настоящее время .
Вам следует прочитать о CORS здесь, но суть этого:
Совместное использование ресурсов между источниками (CORS) - это механизм, который использует
дополнительные заголовки HTTP, чтобы указать браузерам предоставить веб-приложение
работает в одном источнике, доступ к выбранным ресурсам из другого
источник. Веб-приложение выполняет HTTP-запрос из разных источников, когда оно
запрашивает ресурс другого происхождения (домен, протокол или
порт) из собственного.
-
происхождение определяется тремя вещами: протоколом , портом и хостом . Так, например,
https://web.com
имеет другое происхождение, чем http://web.com
(другой протокол) и https://web.com:8081
(другой порт) и, очевидно, https://thatotherweb.net
(другой хост)
Для записи: НЕ используйте JSONP, если вы не доверяете серверу, с которым разговариваете, на 100%. Если он будет скомпрометирован, ваша веб-страница будет тривиально взломана.
Также обратите внимание, что JSONP может быть взломан, если не реализован правильно.
Я хотел бы отдать должное автору JSONP, который изложил его философию: Архив Боба Ипполито на JSONP. Он представляет JSONP как «новую технологически независимую стандартную методологию для метода тегов сценария для междоменной выборки данных».