Пользователь
0,0
рейтинг
24 февраля 2011 в 17:41

Разработка → Кроссдоменный AJAX

На вопрос, как сделать AJAX запрос к другому домену, я всегда отвечал, что никак, и предлагал в качестве альтернативы jsonp, прокси, флеш, фреймы. Но, оказывается, большинство современных браузеров (IE8+, FF3.5+, Chrome 6+ и Safari 4+) вполне поддерживает кроссдоменный XMLHTTPRequest.

С клиентской стороны все остается без изменений. Только теперь браузер не блокирует запрос при отправке, а добавляет к нему заголовок с именем домена, откуда делается запрос: Origin: example.com

Ответ от сервера он так просто назад не пропускает, сервер должен добавить специальный заголовок: Access-Control-Allow-Origin: *
Вместо звездочки сервер может указать конкретный домен, которому разрешено получить ответ.

Вот такое элегантное решение. Без лишних HTTP запросов, без изменения клиентского API, без нарушения безопасности существующих приложений (ведь подгрузить картинку с другого домена или отправить форму в ифрейм можно было и раньше), и наконец, в отличие от Флеша, с гибкой настройкой прав доступа к индивидуальным страницам.

Спецификация CORS (англ.)
Поддержка в браузерах (англ.)
Соображения безопасности (англ.)
easyXDM — альтернативное решение, работает без Флеша во всех браузерах
Алексей Лебедев @alisey
карма
95,2
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (22)

  • +6
    Оно бы да, но в FF3.6 это почему-то отключили. В 3.5 работало. Статья ejohn.org/blog/cross-site-xmlhttprequest/, в ней пример по ссылке «Demo». Он не работает не потому, что там что-то отключено, хотя может быть и так. Я проверял на своих серверах в FF3.6 — не работает. До FF3.5 существовал даже плагин FF, реализующий этот механизм.

    Вот если бы в статье осветили именно эти подводные течения — почему отключили, что тестируют, когда включат? — то ценность статьи была бы намного выше.

    Из фактов про FF ещё скажу, что Greasemonkey каким-то образом раскрывает кроссдоменность, и у неё GM_xttprequest() кроссдоменно работает. Значит, в браузере есть протокол? как его включить? Почему тогда не реализовали его в том полагине, который работает до версии 3.5? Самое интересное, что при запросе HTTPAnalyzer виден приход ответа с чужого домена со всей информацией по методу с Access-Control-Allow-Origin, но браузер его в себя не пропускает.
    • 0
      Ну, они написали в Release Notes, что спецификация часто меняется, и вместо того, чтобы каждый раз менять код, они лучше подождут более стабильной спецификации.
    • 0
      В 3.6.13 вчера тестировал, все прекрасно работало.
      • 0
        Вот, наверное, что работало и работает (FF, Хром, Safari; Опера и IE8 (Win7x64) — не): arunranga.com/examples/access-control/simpleXSInvocation.html (ссылка со страницы hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ под заголовком "“Simple” Requests using GET or POST". Для Post демо: arunranga.com/examples/access-control/preflightInvocation.html.

        С особенностью: “Simple” requests don’t set custom headers, and the request body only uses plain text (namely, the text/plain Content-Type).

        CORS, скорее всего, НЕ будет работать, именно он работал до 3.5, но проверить ещё раз сейчас не могу.

        Так же работает в FF описанный ниже в той же статье метод с request.withCredentials = «true»; для передачи куков.

        В общем, много интересного в современном состоянии XDR.
        • 0
          У Резига там просто пример с устаревшей версией протокола, поэтому и не работает. Вместо «Access-Control-Allow-Origin» там используется «Access-Control: allow». Запрет на кастомные хедеры — это логично, они хотят избежать потенциальных проблем с безопасностью, и поэтому не разрешают XDR отсылать ничего такого, что нельзя отослать с помощью обычной формы.
  • 0
    А опера не рассматривалась или не поддерживает?
    • 0
      Не поддерживает, политика безопасности…
  • +2
    Обычно использую связку
    Аджакс на внутренний файл, а он уже отправляет через CURL то что мне нужно.

    Конечно внутренний файл защищается.
    • +4
      Тут вместо IP юзера запрос придет с IP вашего сервера. Если кол-во запросов с IP ограничено, то будет плохо.
      • 0
        Оригинальный IP можно передать в качестве дополнительного заголовка, а вот второе просто так не вылечить.
    • 0
      nginx proxy вам в помощь.
  • 0
    Вспомнилось. Помоему отличное решение.
    А CORS пока на мой взгляд слишком не безопасный.
    достаточно внедрить скрипт куда-либо который с этого домена сделает запрос на нужный хакеру домен а тот уже зная что пришло сделает просто Access-Control-Allow-Origin такойже какой к нему пришёл Origin.
    По-моему совершенно не безопасно.
    Я конечно понимаю что с таким же успехом можно использовать jsonp для таких целей, но с добавлением CORS руки развяжут разработчикам сайтов и разработчикам троянов.
  • –2
    Если трактовать AJAX широко, не только как XMLHTTPRequest, вполне себе без ифреймов решается легко и элегантно через dom —
    var objScript = document.createElement('script');
    objScript.src =… // target url goes here

    • 0
      полный пример копи-паст выглядит так:

      • +1
        var headID = document.getElementsByTagName(«head»)[0];
        var newScript = document.createElement('script');
        newScript.type = 'text/javascript';
        newScript.src = 'http://www.somedomain.com/somescript.js';
        headID.appendChild(newScript);
        • –1
          Хорошее решение! JSONP решает! =)
          • +2
            а за что минусы? это лучше чем через PHP, делая +1 cURL запрос на каждый AJAX-запрос.

            Я к cURL прибегаю только тогда, когда у меня нет доступа к серверной части при кроссдоменном запросе.
  • 0
    Думаю, пока не появится более стабильная версия, придется все же использовать слой из ПХП. Зато шифрование доступно так.
  • +1
    Использую plugins.jquery.com/plugin-tags/cross-domain и горя не знаю
  • 0
    YQL

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.