- JSONP
-
JSONP или «JSON with padding» (JSON с набивкой) это дополнение к базовому формату JSON. Он предоставляет способ запросить данные с сервера, находящегося в другом домене — операцию, запрещённую в типичных веб-браузерах из-за политики ограничения домена.
По правилу ограничения домена веб-страница, доставляемая с сервера server1.example.com, не может нормально связаться с сервером, отличным от server1.example.com. Исключением является HTML-элемент
<script>
. Эксплуатируя открытую политику для элементов<script>
, некоторые страницы используют их, чтобы загружать JavaScript-код, оперирующий динамически создаваемыми JSON-данными из других источников. Этот шаблон поведения известен как JSONP. Запросы для JSONP получают не JSON, а произвольный JavaScript-код. Они обрабатываются интерпретатором JavaScript, а не парсером JSON.О JSONP возникают критические отзывы. Cross-origin resource sharing (CORS) является более новым методом получения данных с сервера в другом домене. Он учитывает критику.
Содержание
Как это работает
Чтобы понять, как работает этот паттерн, сперва представьте запрос по некоему URL, возвращающий JSON-данные. Программа на JavaScript могла бы запросить этот URL, к примеру, посредством XMLHttpRequest. Предположим, UserId объекта Foo равен 1234. Браузер, запрашивающий URL
http://server2.example.com/Users/1234
, передав Id равный 1234, получил бы ответ вроде:{"Name": "Foo", "Id": 1234, "Rank": 7}
Эти JSON-данные могли бы быть динамически созданными согласно параметрам запроса, переданным в URL.
Ниже HTML-элемент
<script>
указывает в качестве атрибутаsrc
ссылку, возвращающую JSON:<script type="text/javascript" src="http://server2.example.com/Users/1234"> </script>
В свою очередь, браузер скачает файл
script
, разберёт его содержимое, интерпретирует сырые JSON-данные как блок, и выкинет ошибку синтаксиса. Даже если данные были интерпретированы как литеральный объект JavaScript, к нему невозможно получить доступ из JavaScript, выполняемого в браузере, поскольку без присвоения переменной объектные литералы недоступны.В паттерне JSONP, URL, на который указывает атрибут src тэга
<script>
, возвращает данные JSON, обёрнутые в вызов функции. В подобном случае функция, уже определённая в среде JavaScript, может манипулировать JSON-данными. Начинка JSONP может выглядеть так:functionCall({"Name": "Foo", "Id": 1234, "Rank": 7});
Вызов функции это и есть «P» в слове JSONP — «padding» (набивка, «отступ») вокруг чистого JSON, или, согласно некоторым источникам[1] — «префикс». По соглашению, браузер передаёт имя функции обратного вызова как именованный параметр запроса, обычно используя имя
jsonp
илиcallback
в запросе к серверу, то есть,<script type="text/javascript" src="http://server2.example.com/Users/1234?jsonp=parseResponse"> </script>
В данном примере начинка будет такова:
parseResponse({"Name": "Foo", "Id": 1234, "Rank": 7});
Набивка
В то время как набивка (префикс) является обычно именем функции обратного вызова, определённой внутри контекста выполнения в браузере, она может также быть переменной, оператором if, или любым другим оператором JavaScript. Ответ на JSONP-запрос (строго говоря — запрос, соответствующий паттерну JSONP) не является JSON и не парсится как JSON; начинка может быть любым выражением на JavaScript, и вовсе не требует, чтобы внутри обязательно был JSON. Но обычно это фрагмент JavaScript, применяющий вызов функции к неким JSON-данным.
Другими словами, типичное применение JSONP предоставляет меджоменный доступ к существующему JSON API путём оборачивания начинки JSON в вызов функции.
Инжекция элемента script
JSONP имеет смысл только когда используется с элементом script. Для каждого нового JSONP-запроса браузер должен добавить новый элемент
<script>
или использовать существующий. Первая манипуляция — добавление нового элемента script — осуществляется через динамическое манипулирование DOM, и известна как инжекция элемента script. Элемент<script>
впрыскивается в HTML DOM, с URL желаемой конечной точки JSONP в атрибуте «src».Эта динамическая инжекция элемента script обычно выполняется вспомогательной библиотекой javascript. У jQuery и других фреймворков имеются вспомогательные функции для JSONP; существуют также и отдельные решения.[2][3]
Динамически вставляемый элемент script для вызовов JSONP выглядит следующим образом:
<script type="text/javascript" src="http://server2.example.com/Users/1234?jsonp=parseResponse"> </script>
После вставки элемента, браузер обрабатывает его и выполняет HTTP GET для src URL, получая содержимое. Затем браузер обрабатывает возвращённую полезную начинку как javascript. Обычно это выполнение функции.
В этом смысле применение JSONP можно охарактеризовать как разрешить браузерным страницам обойти политику ограничения домена путём вставки элемента script.
Соображения по безопасности
Включение тэгов script с других серверов позволяет удалённым серверам подмешать в веб-сайт любое содержимое. Если у удалённых серверов есть уязвимости, допускающие подмешивание JavaScript, страница, предоставляемая оригинальным сервером, подвергается повышенному риску.
В настоящее время предпринимаются шаги, чтобы определить более безопасное строгое подмножество JSON-P[4], которое браузеры могли бы принудительно включать при запросах скрипта со специфичным MIME-типом, как например «application/json-p». Если ответ не парсится как строгий JSON-P, браузер мог бы выводить ошибку или просто игнорировать весь ответ. Однако, на текущий момент единственным правильным MIME-типом для JSONP является «application/javascript».[5]
Подделка межсайтовых запросов
Примитивные размещения JSONP подвержены опасности подделки межсайтовых запросов (CSRF или XSRF).[6] Поскольку HTML-тэг
<script>
не подчиняется политике ограничения домена в реальных реализациях браузеров, вредоносная страница может запросить и получить JSON-данные, принадлежащие другому сайту. Это позволит данным в формате JSON быть обработанными в контексте вредоносной страницы, возможно, раскрывая пароли или другие секретные данные, если пользователь залогинен на другом сайте.Это вызывает проблемы только если данные, закодированные в JSON, содержат конфиденциальную информацию, которую нельзя разглашать третьей стороне, и сервер полагается на политику ограничения домена браузера для блокировки передачи данных в случае неправильного запроса. Проблема не существует, если сервер самостоятельно определяет уместность запроса, передавая данные только если запрос правильный. Cookies сами по себе не являются адекватным способом определения правомерности запроса. Использование одних лишь только cookies подвержено подделке межсайтовых запросов.
References
- ↑ Experimental RDF result set to JSON translator. Проверено 20 февраля 2012.
- ↑ example jsonp library on pastebin.
- ↑ jQuery's $.getJSON utility.
- ↑ Safer cross-domain Ajax with JSON-P/JSONP. JSON-P.org. Проверено 30 октября 2011.
- ↑ Grey, Eli Is this safe for providing JSONP?. stackoverflow.com (27 июня 2010). Проверено 7 сентября 2012.
- ↑ Grossman, Jeremiah Advanced Web Attack Techniques using GMail (January 27, 2006). Проверено 3 июля 2009.
External links
Категории:- AJAX
- JSON
Wikimedia Foundation. 2010.