Как делиться файлами cookie из разных источников? В частности, как использовать Set-Cookie
заголовок в сочетании с заголовком Access-Control-Allow-Origin
?
Вот объяснение моей ситуации:
Я пытаюсь установить файл cookie для API, который работает localhost:4000
в веб-приложении, на котором размещено localhost:3000
.
Кажется, я получаю правильные заголовки ответов в браузере, но, к сожалению, они не действуют. Это заголовки ответа:
HTTP / 1.1 200 ОК Доступ-Контроль-Разрешить-Происхождение: http: // localhost: 3000 Варьируется: происхождение, кодирование-принятие Set-Cookie: token = 0d522ba17e130d6d19eb9c25b7ac58387b798639f81ffe75bd449afbc3cc715d6b038e426adeac3316f0511dc7fae3f7; Макс-возраст = 86400; Домен = localhost: 4000; Путь = /; Срок действия истекает = Вт, 19 сентября 2017 г., 21:11:36 GMT; HttpOnly Тип содержимого: приложение / json; charset = utf-8 Длина содержимого: 180 ETag: W / "b4-VNrmF4xNeHGeLrGehNZTQNwAaUQ" Дата: пн, 18 сентября 2017 г., 21:11:36 GMT Подключение: keep-alive
Кроме того, я вижу файл cookie, Response Cookies
когда проверяю трафик на вкладке «Сеть» в инструментах разработчика Chrome. Тем не менее, я не вижу, чтобы файл cookie был установлен на вкладке «Приложение» ниже Storage/Cookies
. Я не вижу ошибок CORS, поэтому полагаю, что мне не хватает чего-то еще.
Какие-либо предложения?
Обновление I:
Я использую модуль запроса в приложении React-Redux для отправки запроса /signin
конечной точке на сервере. Для сервера использую экспресс.
Экспресс-сервер:
res.cookie ('токен', 'xxx-xxx-xxx', {maxAge: 86400000, httpOnly: true, domain: 'localhost: 3000'})
Запрос в браузере:
request.post ({uri: '/ signin', json: {userName: 'userOne', пароль: '123456'}}, (err, response, body) => { // делаем что-то })
Обновление II:
Я как сумасшедший настраиваю заголовки запроса и ответа, убеждаясь, что они присутствуют как в запросе, так и в ответе. Ниже скриншот. Обратите внимание на заголовки Access-Control-Allow-Credentials
, Access-Control-Allow-Headers
, Access-Control-Allow-Methods
и Access-Control-Allow-Origin
. Глядя на проблему, которую я обнаружил на github Axios , у меня сложилось впечатление, что все необходимые заголовки теперь установлены. Но все равно не повезло ...
источник
request
модуль не предназначен для использования в браузере. Axios, похоже, пока отлично справляется. Теперь я получаю и заголовок:Access-Control-Allow-Credentials:true
иAccess-Control-Allow-Origin:http://localhost:3000
(используется для включения CORS). Это кажется правильным, ноSet-Cookie
заголовок ничего не делает ...{ withCredentials: true }
это действительно требуется для стороны Axios, заголовки серверов также должны быть тщательно проверены (см. Stackoverflow.com/a/48231372/488666 )Ответы:
Что тебе необходимо сделать
Чтобы разрешить прием и отправку файлов cookie по запросу CORS, выполните следующие действия.
Back-end (сервер): установите
Access-Control-Allow-Credentials
значение заголовка HTTP равнымtrue
. Кроме того, убедитесь, что заголовки HTTPAccess-Control-Allow-Origin
иAccess-Control-Allow-Headers
установлены без подстановочного знака*
.Для получения дополнительной информации о настройке CORS в express js прочтите документы здесь
Внешний интерфейс (клиент): установите этот
XMLHttpRequest.withCredentials
флагtrue
, это может быть достигнуто разными способами в зависимости от используемой библиотеки запроса-ответа:jQuery 1.5.1
xhrFields: {withCredentials: true}
ES6 fetch ()
credentials: 'include'
аксиомы :
withCredentials: true
Или
Избегайте использования CORS в сочетании с файлами cookie. Вы можете добиться этого с помощью прокси.
Если вы по какой-то причине не избегаете этого. Решение выше.
Оказалось, что Chrome не будет устанавливать cookie, если домен содержит порт. Настроить его на
localhost
(без порта) не проблема. Большое спасибо Эрвину за этот совет!источник
localhost
проверки здесь: stackoverflow.com/a/1188145, а также это может помочь вашему делу ( stackoverflow.com/questions/50966861/… )Access-Control-Allow-Origin
явного домена, а не просто"*"
. Тогда это был бы идеальный ответПримечание для браузера Chrome, выпущенного в 2020 году.
Поэтому, если ваш внутренний сервер не устанавливает SameSite = None, Chrome будет использовать SameSite = Lax по умолчанию и не будет использовать этот файл cookie с запросами {withCredentials: true}.
Подробнее https://www.chromium.org/updates/same-site .
Разработчики Firefox и Edge также хотят выпустить эту функцию в будущем.
Здесь указаны спецификации: https://tools.ietf.org/html/draft-west-cookie-incrementalism-01#page-8
источник
Для того, чтобы клиент мог читать файлы cookie из запросов из разных источников, вам необходимо иметь:
Все ответы от сервера должны содержать в заголовке следующее:
Access-Control-Allow-Credentials: true
Клиент должен отправлять все запросы с
withCredentials: true
опциейВ моей реализации с Angular 7 и Spring Boot я добился этого с помощью следующего:
На стороне сервера:
origins = "http://my-cross-origin-url.com"
Часть будет добавитьAccess-Control-Allow-Origin: http://my-cross-origin-url.com
в заголовок ответа каждого сервераЭта
allowCredentials = "true"
часть будет добавлятьсяAccess-Control-Allow-Credentials: true
к заголовку ответа каждого сервера, что нам нужно, чтобы клиент мог читать файлы cookie.Сторона клиента:
С помощью этого класса вы фактически добавляете дополнительный материал во все свои запросы.
Первая часть
req = req.clone({ withCredentials: true });
- это то, что вам нужно для отправки каждого запроса сwithCredentials: true
опцией. Практически это означает, что запрос OPTION будет отправлен первым, так что вы получите свои файлы cookie и токен авторизации среди них, прежде чем отправлять фактические запросы POST / PUT / DELETE, которым этот токен должен быть прикреплен к ним (в заголовке) в приказ серверу проверить и выполнить запрос.Вторая часть - это та, которая специально обрабатывает токен анти-CSRF для всех запросов. При необходимости считывает его из файла cookie и записывает в заголовок каждого запроса.
Желаемый результат выглядит примерно так:
источник
allowCredentials = "true"
в@CrossOrigin
аннотации.Ответ Пима очень полезен. В моем случае я должен использовать
Если это dateTime, даже если срок его действия не истек, он все равно не отправит cookie в бэкэнд:
Надеюсь, это будет полезно для будущих людей, которые могут столкнуться с той же проблемой.
источник
Для экспресс-обновления обновите свою экспресс-библиотеку до
4.17.1
последней стабильной версии. Затем;В CorsOption: Установить
origin
на свой локальный URL или производственной интерфейс URL иcredentials
кtrue
примеруЯ устанавливаю свое происхождение динамически, используя модуль config npm .
Затем в res.cookie:
Для локального хоста: вам не нужно устанавливать sameSite и безопасный вариант на всех, вы можете установить ,
httpOnly
чтобыtrue
для HTTP куки , чтобы предотвратить XSS атаку и другие полезные опции в зависимости от вашего использования.Для производственной среды, вам необходимо установить
sameSite
дляnone
запроса кросс-происхождения иsecure
кtrue
. Помните,sameSite
работает только с последней версией Express, а последняя версия Chrome устанавливает только cookie поверхhttps
, поэтому требуется безопасный вариант.Вот как я сделал свой динамичный
источник