CORS - как выполнить предварительную проверку httprequest?

94

Я пытаюсь сделать междоменный HTTP-запрос к службе WCF (которая принадлежит мне). Я прочитал несколько методов работы с ограничениями междоменного сценария. Поскольку моя служба должна обрабатывать запросы GET и POST, я не могу реализовать какой-либо тег динамического сценария, src которого является URL-адресом запроса GET. Поскольку я могу вносить изменения на сервере, я начал пытаться реализовать обходной путь, который включает в себя настройку ответов сервера для включения заголовка «Access-Control-Allow-Origin» и запросов предварительной проверки с запросом OPTIONS. Я получил идею из этого сообщения: Как заставить работать CORS

На стороне сервера мой веб-метод добавляет в HTTP-ответ «Access-Control-Allow-Origin: *». Я вижу, что ответы теперь включают этот заголовок. Мой вопрос: как выполнить предварительную проверку запроса (ВАРИАНТЫ)? Я использую jQuery.getJSON для выполнения запроса GET, но браузер сразу же отменяет запрос с печально известной:

Источник http: // localhost не разрешен Access-Control-Allow-Origin

Кто-нибудь знаком с этой техникой CORS? Какие изменения необходимо внести в клиенте для предварительной обработки моего запроса?

Благодарность!

Ник
источник

Ответы:

159

Во время предварительного запроса вы должны увидеть следующие два заголовка: Access-Control-Request-Method и Access-Control-Request-Headers. Эти заголовки запроса запрашивают у сервера разрешения на выполнение фактического запроса. Ваш предполетный ответ должен подтвердить эти заголовки, чтобы фактический запрос работал.

Например, предположим, что браузер отправляет запрос со следующими заголовками:

Origin: http://yourdomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header

После этого ваш сервер должен ответить следующими заголовками:

Access-Control-Allow-Origin: http://yourdomain.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: X-Custom-Header

Обратите особое внимание на заголовок ответа Access-Control-Allow-Headers. Значение этого заголовка должно быть таким же, как в заголовке запроса Access-Control-Request-Headers, и не может быть «*».

Как только вы отправите этот ответ на предварительный запрос, браузер сделает фактический запрос. Вы можете узнать больше о CORS здесь: http://www.html5rocks.com/en/tutorials/cors/

монсур
источник
не могли бы вы добавить несколько доменов в Access-Control-Allow-Origin?
бот-бот
@botbot Вы, наверное, уже разобрались с этим, но на случай, если другие задаются вопросом, можете лиAccess-Control-Allow-Origin: *
Стив Чемберс,
2
Возможно, я что-то упустил. Так я должен отправить два запроса XMLHttp? Один для предполетной подготовки; проверить ответ в случае успеха, а затем отправить фактический запрос?
Kangkan
15
@Kangkan, вам не нужно беспокоиться об отправке предполетного запроса. Если для запроса требуется предварительная проверка, браузер отправит его за вас.
monsur
4
СПАСИБО за бит `` обратите особое внимание '' ... который решил мою проблему с node / expressjs, я смог добавить фильтр, чтобы перехватить эти предполетные запросы//cors and preflight filtering app.all('*', function(req, res, next){.. //preflight needs to return exact request-header res.set('Access-Control-Allow-Headers', req.headers['access-control-request-headers']); if ('OPTIONS' == req.method) return res.send(204);next(); });
Kurtfm
0

Хотя эта цепочка восходит к 2014 году, проблема может быть актуальной для многих из нас. Вот как я справился с этим в контексте jQuery 1.12 / PHP 5.6:

  • jQuery отправил свой запрос XHR, используя только ограниченные заголовки; было отправлено только "Origin".
  • Никаких предполетных запросов не требовалось.
  • Серверу нужно было только обнаружить такой запрос и добавить «Access-Control-Allow-Origin:». Заголовок $ _SERVER ['HTTP_ORIGIN'] после обнаружения XHR перекрестного происхождения.

Пример кода PHP:

if (!empty($_SERVER['HTTP_ORIGIN'])) {
    // Uh oh, this XHR comes from outer space...
    // Use this opportunity to filter out referers that shouldn't be allowed to see this request
    if (!preg_match('@\.partner\.domain\.net$@'))
        die("End of the road if you're not my business partner.");

    // otherwise oblige
    header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
}
else {
    // local request, no need to send a specific header for CORS
}

В частности, не добавляйте, exit;поскольку предварительная проверка не требуется.

Фабьен Хаддади
источник