Запрос CORS с предварительной проверкой и перенаправлением: запрещен. Обходные пути?

Я разрабатываю API, который позволяет пользователю аутентифицироваться (используя токены) и содержит перенаправления в том же домене. Теперь для неаутентифицированного запроса к конечной точке, который возвращает 303,

GET /documents/123  --> 303 redirect to `/documents/abc`
GET /documents/abc  --> 200

все получается красиво.

Давайте сделаем аутентифицированный запрос к той же конечной точке, куда отправляется заголовок Authorization. Это делает запрос предварительным запросом, и браузер выполняет предварительный OPTIONS запрос, т. е.

OPTIONS /documents/123   --> 204 (everything okay, please proceed)
GET /documents/123       --> 303 redirect to `/documents/abc`

В этот момент вместо GETобозначения фактического ресурса в /documents/abc браузер выдает

XMLHttpRequest cannot load http://localhost:8000/people/username/nschloe. 
The request was redirected to 'http://localhost:8000/people/YDHa-B2FhMie', 
which is disallowed for cross-origin requests that require preflight.

Это поведение соответствует стандарту:

7.1.5 Запрос между источниками с предварительной проверкой

Если ответ имеет код состояния HTTP, который не находится в диапазоне 2xx

Примените шаги сетевой ошибки.

Похоже, это означает, что нельзя выполнять перенаправления для аутентифицированных ресурсов, даже если перенаправление находится в том же домене (localhost).

Может ли это быть правдой? Есть ли общий обходной путь?


person Nico Schlömer    schedule 22.01.2016    source источник
comment
Как выглядят ваши заголовки ответов? Особенно заголовки Access-Control-Allow-Headers?   -  person Sam    schedule 22.01.2016
comment
Для предварительного запроса OPTIONS у меня есть Access-Control-Allow-Headers:Accept, Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, Accept-Encoding.   -  person Nico Schlömer    schedule 22.01.2016
comment
Вы имеете в виду, что это для перенаправленного URL-адреса /documents/abc, верно?   -  person Sam    schedule 22.01.2016
comment
Запрос на перенаправление никогда не выполняется; Это проблема. Когда 303 возвращается из GET /documents/123, возвращается ошибка.   -  person Nico Schlömer    schedule 22.01.2016
comment
Хорошо, тогда проблема в том, что во втором случае сгенерирован предварительный запрос, перенаправления не разрешены. Это ограничено политикой перекрестного происхождения. Это не имеет ничего общего с заголовком авторизации как таковым.   -  person Sam    schedule 22.01.2016
comment
Конечно. Мне интересно, является ли это упущением со стороны рабочей группы, поскольку я не понимаю, как тогда вообще можно было бы выполнять аутентифицированные перенаправления.   -  person Nico Schlömer    schedule 22.01.2016
comment
Ну, они против всего, что вызывает перенаправление, поскольку это может привести к проблемам с безопасностью. Вы всегда можете сделать еще один запрос от клиента, если предыдущий запрос был авторизован.   -  person Sam    schedule 22.01.2016
comment
Серверная часть, конечно, может случайно перенаправить клиентов на другие веб-сайты и включить токен. Я бы назвал это ошибкой (безопасности), а не чем-то, что должно быть предписано стандартом. Перенаправление на другой ресурс (даже если это не Same-Origin) является вполне допустимым вариантом использования imho.   -  person Nico Schlömer    schedule 22.01.2016
comment
@NicoSchlömer Вы также можете обновить свой вопрос со ссылкой на github.com/whatwg/fetch/ вопросы/204   -  person sideshowbarker    schedule 23.01.2016
comment
@NicoSchlömer … и, возможно, также ссылку на lists.w3 .org/Archives/Public/public-webappsec/2016Jan/   -  person sideshowbarker    schedule 23.01.2016


Ответы (1)


Исходный стандарт не допускает перенаправления после успешной предварительной проверки CORS. Цитируя § 7.1.5.3:

Это реальный запрос. Примените шаги создания запроса и соблюдайте приведенные ниже правила запроса при создании запроса.

  • Если ответ имеет код состояния HTTP 301, 302, 303, 307 или 308, примените действия по кэшированию и сетевой ошибке.

Благодаря вашим усилиям (спасибо!), 4 августа 2016 года стандарт был обновлен до разрешить перенаправление после успешной предварительной проверки CORS.

Пока браузеры не наверстают упущенное, единственными возможными вариантами могут быть один или их комбинация:

  1. Выполнять перенаправления только для простых запросов.
  2. Выполните перенаправление 305 с вашим собственным URL-адресом в заголовке Location как прокси. Будьте готовы к ограниченной поддержке браузеров, так как 305 устарел.
  3. Сделайте фальшивую переадресацию:
  • вернуть HTML с meta refresh и/или изменением Javascript Location.
  • вернуть HTML с заполнением области просмотра iframe с целью перенаправления в качестве источника iframe.
  • отображать ссылку, по которой пользователь должен щелкнуть, чтобы получить доступ к содержимому.
person bishop    schedule 27.09.2016
comment
какое ожидаемое время для доставки таких изменений браузерами? Это все еще проблема в новейшем chrome/firefox. - person freakman; 24.12.2016
comment
@freakman По моему опыту, между изменением стандартов и их внедрением в последних версиях всех основных браузеров проходит около двух лет. Определенные браузеры могут обновляться быстрее, но в целом я бы сказал, что это август 2018 года. - person bishop; 24.12.2016
comment
Вы даже можете создать HTML-страницу, которая автоматически щелкает скрытую ссылку. Если HTTP POST поддерживается, то даже скрытая форма может быть отправлена ​​​​в конечную точку назначения. - person dvsakgec; 23.01.2017
comment
Исправление для этого добавлено в исходники Blink/Chromium и будет доставлено в Chrome 57 (думаю, выпуск намечен на середину марта). - person sideshowbarker; 11.02.2017
comment
@sideshowbarker Действительно. Я только что обновил Chrome (сейчас работает 57), и теперь поведение изменилось. Работает хорошо! - person fabiomaia; 28.03.2017
comment
Edge и Safari уже были обновлены, чтобы разрешить перенаправление для предварительной проверки, поэтому теперь, когда Chrome также позволяет это, я думаю, что Firefox — единственный, который еще не bugzilla.mozilla.org/show_bug.cgi?id=1346749 - person sideshowbarker; 28.03.2017
comment
У меня версия Chrome «58.0.3029.110 (64-разрядная версия)», и все еще возникают проблемы перед запуском. Я сделал вызов с mytenant.sharepoint.com на домен msprocy.net, который перенаправляется на login.microsoftonline.com. есть идеи? - person Nitin Rastogi; 13.05.2017
comment
@NitinRastogi Я думаю, что проблема, с которой вы столкнулись, - это другая проблема. Изменение, которое было внесено в спецификацию и в Chrome 57, заключается в том, что если сервер отвечает 200 или 204 на предварительную проверку OPTIONS, а затем отвечает на последующий GET с 30x, тогда Chrome 57+ будет теперь следуйте перенаправлению, а не выдавайте ошибку. Но в вашем случае проблема заключается в том, что сервер сам отвечает на запрос OPTIONS с помощью 302. Согласно спецификации CORS (Fetch), ответ 302 на сам запрос OPTIONS не является приемлемым ответом на предварительную проверку. Отсюда и ошибка, которую вы видите. - person sideshowbarker; 14.05.2017