Как работать с CORS и куки

внешний интерфейс

Перевод: сумасшедший технический ботаник

предисловие

CORS и файлы cookie — очень важная проблема во внешнем интерфейсе, но в большинстве случаев, поскольку домены внешнего и внутреннего интерфейса обычно одинаковы, эти проблемы возникают редко. Или просто запросите настройки бэкэндаAccess-Control-Allow-Origin: *Вот и все, совсем немного, чтобы понять механизм операции.

для этой проблемы,MDNПо вышесказанному есть очень подробные пояснения, поэтому данная статья в основном посвящена разбору ключевых моментов и проблем, которые часто возникают в реальной эксплуатации.

Политика того же происхождения

Чтобы предотвратить бурное распространение javascript на веб-страницах, политика одного и того же происхождения предусматривает определенные ресурсы, и код должен быть вгомологияможно получить только доступ.

Что такое гомология? одна порцияdocumentисточник, определяемый протоколом, хостом и портом. То есть, если файл 1 исходит изhttp://kalan.com, а файл 2 взят изhttps://kalan.comОни не гомологичны. А если это субдомен? подобноhttps://api.foobar.comа такжеhttps://app.foobar.com. Поскольку их хосты разные, они не являются одним и тем же источником.

И некоторые ресурсы по своей природе доступны через перекрестное происхождение:

  • <img />
  • <video />,<audio />
  • <iframe />: Вы можете помешать другим встраиваться, определяя заголовок
  • пройти через<link rel="stylesheet" href />Загруженный CSS-скрипт
  • <script src="" />Загруженный Javascript

Запросы между источниками, сделанные с помощью кода, ограничиваются политикой одного и того же источника (например, Fetch, XHR).

Очевидно, что это правило слишком строгое. Если он будет ограничен политикой одного и того же происхождения, разработка интерфейсных и серверных компонентов будет затруднена, и не будет возможности применить API других SDK в качестве XHR. Поэтому появился механизм CORS (Cross-Origin Resource Sharing).

CORS (обмен ресурсами между источниками)

Многие думают, что CORS — это знания, которыми должен обладать только интерфейс. Однако CORS обычно требует, чтобы серверная часть устанавливала соответствующие заголовки HTTP и понимала их значение для правильной работы.

Так как же работают кросс-доменные запросы?

В основном используется для относительного контроля доступа двумя заголовками: в запросеOriginи в ответAccess-Control-Allow-Origin.

Просто отправьте запрос в заголовках Origin и responseAccess-Control-Allow-Originто же значение илиAccess-Control-Allow-Origin: *(это означает, что любому домену разрешен доступ к ресурсам), в настоящее время ограничения на CORS будут ослаблены, что позволит получить доступ к междоменным ресурсам.

Если политика CORS не соблюдается, будет отображаться следующее сообщение:

img

Вы также получите предупреждение, если попытаетесь прочитать возвращаемый объект.

Во-первых, если мы будем следовать подсказкам и изменим режим выборки наno-corsЧто случится? Это правда, что мы избавились от раздражающих сообщений об ошибках, но, похоже, ситуация не улучшается.

no-corsЭто не панацея, даже если вы используете этот паттерн, CORS не откроет из-за этого дверь, то есть ваш запрос не будет успешно отправлен. Он также появилсяSyntaxError: Unexpected end of inputэта ошибка. Этот шаблон обычно используется в сочетании с Service Workers.

Из приведенного выше эксперимента видно, чтоЕсть только один трюк, чтобы снять печать CORS, это добавить правильныйControl-Access-Allow-Origin(хост должен быть таким же, как исходный или*).

Кроме того, механизм CORS работает только тогда, когда javascript отправляет XHR или fetch.Как правило, curl или postman не имеют этого механизма, поэтому он часто игнорируется при тестировании конечных точек API, что приводит к расхождениям между интерфейсом и сервером, когда тестирование API.

Некоторые запросы cross-origin не проходят предварительную проверку, а некоторые — делают, на MDN четко написано:

  1. Должен быть одним из GET, HEAD, POST
  2. Не содержит заголовков, кроме автоматически установленных пользовательским агентом и определенных заголовков. приемлемоheader
  3. если естьContent-Type(обратите внимание на заголовок запроса,не заголовок ответа), оно должно быть одним из следующих значений:application/x-www-form-encoded,text/plain,multipart/form-data

То есть, если вышеуказанные условия не выполняются, будет выдан предварительный запрос.

мы пытаемся поставитьContent-Typeизменить наapplication/jsonпроверить это (не могуapplication/x-www-form-encoded,text/plain,multipart/form-data).

Preflight

Так называемая предварительная проверка заключается в том, что запрос сначала будет использовать метод HTTP OPTION, чтобы постучать в дверь другого домена, а настоящий запрос будет отправлен только после подтверждения отсутствия проблемы. Как только это условие срабатывает, все становится намного более громоздким.

  1. Необходимо присоединиться к OPTIONS одной и той же конечной точке API,И установите Access-Control-Allow-Origin для соответствия условиям CORS.
  2. должен присоединитьсяAccess-Control-Allow-Headers, и должен содержатьвсеЗаголовок не входит в условие, иначе оно не пройдет.

Если предпечатная проверка не пройдена, сообщение об ошибке будет следующего вида:

Access to fetch at 'http://localhost:3001/trigger-preflight' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

или ты не тамOPTIONSдобавить в заголовок ответаAccess-Control-Allow-Origin:

Access to fetch at 'http://localhost:3001/trigger-preflight' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

В случае успеха вы увидите два запроса в сети, один OPTIONS, а другой реальный запрос.

OPTION

GET

Картинка выше ВАРИАНТ, картинка ниже ПОЛУЧИТЬ

Что, если мы добавим самодельный заголовок? В соответствии с условиями, определенными MDN, предварительный запрос также должен быть запущен.X-Access-TokenПосмотрите, что происходит.

Пройти предполетную проверку действительно невозможно.Если хотите пройти, то должны поставитьX-Access-TokenПрисоединяйсяAccess-Control-Allow-Headersсередина.

запрос с аутентификацией

Файлы cookie не могут передаваться между доменами, а это означает, что файлы cookie из разных источников не могут передаваться и получать доступ друг к другу, иначе мир погрузится в хаос.

Однако, если вы отправляете запрос в домен b в домене a, а домен b возвращает информацию о файлах cookie, то файл cookie будет храниться в домене a в виде домена b, если он не установленwithCredentialsилиcredentials: ‘include’Если да, то даже если сервер вернетсяSet-Cookie, то же не будет написано. Как показано ниже:

服务器回传Set-Cookie

Сервер возвращает Set-Cookie

没有写入到浏览器中

не пишется в браузере

В обычных условиях, если снова используется API домена b, файл cookie не будет автоматически отправлен. В этом случае вы должныXHRнастраиватьwithCredentialsилиfetchустановить в опциях{ credentials: 'include' }, так как это тоже междоменный запрос, он тоже должен быть присоединен согласно условиям CORSAccess-Control-Allow-Origin

Во избежание проблем с безопасностью браузеры также имеют правилаAccess-Control-Allow-Originне может быть*.

Access to fetch at 'http://localhost:3001/cookie' from origin 'http://localhost:3000' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

Но этого недостаточно, браузер автоматически не отклонитAccess-Control-Allow-Credentialsответ, поэтому, если вы хотите передать идентификационную информацию на междоменный сервер, вы должны добавить дополнительныйAccess-Control-Allow-Credentials: true. Если они установлены успешно, это должно выглядеть так, как показано на рисунке ниже.В Request Cookie вы можете увидеть, что cookie был успешно отправлен.

Request Cookies 里有个 jack!

В Request Cookies есть гнездо!

Что ж, если вы успешно настроили эти вещи, все еще возможно, что нет никакого способа получить cookie на сервер. Это могут быть следующие ситуации:

1. Пользователь отключил файлы cookie для этого домена.

Возможно, пользователь добавил вас в черный список, поэтому cookie не может быть успешно отправлен

Решение:

  • изменить домен
  • Проверьте, почему вы заблокированы пользователями
2. Пользователь блокирует файлы cookie со всех внешних веб-сайтов.

Параметр «Блокировать все файлы cookie» иногда включается в Safari, что может причинить вам много боли при отладке.

постскриптум

Неблагодарное дело иметь дело с CORS, особенно иногда забывая добавить его перед запуском CI/CDAccess-Control-Allow-OriginилиAccess-Control-Allow-Credentials, то развертывание может занять еще один день. На этот раз я разобрался с некоторыми распространенными проблемами, надеюсь, что если возникнет подобная ситуация в будущем, я смогу знать, как с ней справиться.

Наконец прикрепленисходный код.

Справочная статья

Добро пожаловать в официальный аккаунт: Front-end Pioneer, получите больше фронтенд-галантереи.