Файлы cookie недоступны в JavaScript (и инструментах разработки) , но отправляются вместе с запросом XHR (не используется httponly)
я использую как интерфейсное, так и серверное приложение в другом домене с авторизацией на основе сеанса. У меня есть настройка рабочей конфигурации CORS, которая работает так, как ожидалось на localhost
(например, из порта :9000
в порт :8080
). Как только я развертываю приложения на защищенных доменах (оба домена разрешают только HTTPS), файл cookie CSRF больше не доступен в JavaScript, что приводит к неправильному последующему запросу интерфейса (отсутствует CSRF заголовок.)
файл cookie устанавливается задней частью в Set-Cookie
заголовок без С помощью HttpOnly
флаг. Он фактически установлен где-то в браузере, потому что последующий запрос содержит как файл cookie сеанса, так и файл cookie CSRF. Попытка доступа к нему с помощью JavaScript (например,document.cookie
в консоли) возвращает пустую строку. DevTools Chrome не показывают любой cookies на интерфейсном домене (внутренний домен даже не перечисленный.)
Я ожидаю, что cookie будет установлен и будет виден в текущем домене (интерфейсный домен). Я использую withCredentials
флаг axios библиотека.
у вас есть идеи, почему файл cookie не может быть доступен из JavaScript или из DevTools в Chrome? Имеет ли это какое-либо отношение к Strict-Transport-Security
заголовок?
заголовки
1. Первоначальный ответ GET Заголовок
HTTP/1.1 401 Unauthorized
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://[my-frontend-domain]
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Encoding: gzip
Content-Type: application/json;charset=UTF-8
Date: Wed, 20 Sep 2017 11:57:07 GMT
Expires: 0
Pragma: no-cache
Server: Apache-Coyote/1.1
Set-Cookie: CSRF-TOKEN=[some-token]; Path=/
Vary: Origin,Accept-Encoding
X-Content-Type-Options: nosniff
X-Vcap-Request-Id: [some-token]
X-Xss-Protection: 1; mode=block
Content-Length: [some-length]
Strict-Transport-Security: max-age=15768000; includeSubDomains
2. Заголовок последующего запроса POST
POST /api/authentication HTTP/1.1
Host: [my-backend-host]
Connection: keep-alive
Content-Length: [some-length]
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
Origin: [my-frontend-host]
User-Agent: [Google-Chrome-User-Agent]
Content-Type: application/x-www-form-urlencoded
DNT: 1
Referer: [my-frontend-host]
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,de-CH;q=0.2,it;q=0.2
Cookie: [some-other-cookies]; CSRF-TOKEN=[same-token-as-in-the-previous-request]
этот запрос должен содержать заголовок CSRF, который будет автоматически добавлен, если файл cookie доступен с помощью JavaScript.
4 ответов
короче говоря, невозможно получить доступ к куки-файлам cross-origin,document.cookie
доступ только к текущему (или родитель) доменные cookies.
намек на то, что это является основной причиной, был SSC-hrep3, упоминая "оба домена" в своем вопросе.
очень легко сделать эту ошибку при переключении с развертывания localhost, используя только разные порты для серверных и интерфейсных серверов, на тот, который использует два разных хоста. Это будет работать локально, потому что cookies являются общими для всех портов и не будут работать при использовании двух разных хостов. (В отличие от некоторых других проблем CORS, которые также будут отображаться локально)
посмотреть ответ ssc-hrep3 для получения дополнительной информации и решения.
1
вам может потребоваться добавить Управление Доступом-Разрешить-Заголовки заголовок, чтобы разрешить передачу определенных заголовков.
пожалуйста, попробуйте добавить следующее в заголовки ответов сервера (метод опций) для целей тестирования
Access-Control-Allow-Headers: Content-Type, *
в производстве я рекомендую ограничить заголовки следующим образом (но я не уверен на 100% в правильном списке заголовков, нужно экспериментировать здесь, если это работает)
Access-Control-Allow-Headers: Cookie, Set-Cookie
для справки https://quickleft.com/blog/cookies-with-my-cors/
2
еще одна проблема, которую вы можете experince является то, что вы cookies будут установлены на том домене, где находится ваш серверный сервис (не в домене, из которого вы запрашиваете)
пожалуйста, проверьте это
3
в качестве опции последней проблемы-браузер может запретить установку cookie для домена b.xxx.com
запрос, который приходит от a.xxx.com
в этом случае вы можете попробовать установить cookie в Родительском домене xxx.com
, поэтому он будет доступен для вашей стороны клиента
TL; DR: чтение-доступ к междоменным cookies невозможен. Добавление токена CSRF в заголовок ответа было бы решением. Другим решением для полного обхода CORS & междоменных запросов было бы использование обратного прокси-сервера.
как указано в моем вопросе выше, часть JavaScript моего интерфейса (например,https://example1.com
пытается получить доступ к не-HttpOnly
cookie из моего бэк-энда, например https://example2.com
. Чтобы иметь доступ к a удаленный API с JavaScript, я использую CORS. Это позволяет выполнять запросы. Я использую withCredentials: true
на лицевой стороне и Access-Control-Allow-Credentials: true
на задней стороне. The Set-Cookie
заголовок затем устанавливает файл cookie на внутреннем источнике, а не на интерфейсном источнике. Поэтому cookie не отображается ни в DevTools, ни в document.cookie
команда в JavaScript.
Cookies, установленные на back-end origin, всегда являются частью запроса к back-end через CORS. Однако мне нужен доступ. к контент файла cookie CSRF для добавления маркера в заголовок запроса (для предотвращения атак CSRF). Как я узнал, нет способа читать (или писать) куки из другого домена с помощью JavaScript-независимо от того, какая настройка CORS используется (см. эти ответы StackOverflow: [1], [2]). Браузер ограничивает доступ к содержимому файла cookie для одного и того же домена.
решений
это приводит к выводу,, что нет возможности получить доступ к содержимому безHttpOnly
cookie другого домена. Обходным путем для этой проблемы было бы установить токен CSRF в дополнительный пользовательский заголовок ответа. Эти заголовки обычно также не могут быть доступны в другом домене. Однако они могут быть подвержены настройке CORSAccess-Control-Expose-Headers
. Это безопасно, пока используется строго ограниченный Access-Control-Allow-Origin
заголовок.
другим обходным путем было бы использование обратного прокси-сервера, который обходит проблемы с CORS и междоменными запросами вообще. Использование такого обратного прокси обеспечивает специальный путь на интерфейсе, который будет перенаправлен на серверную часть. Например, вызовы https://front-end/api
прокси для https://back-end/api
. Поскольку все запросы от интерфейсного сервера выполняются к интерфейсному прокси-серверу в том же домене, браузер рассматривает каждый вызов как запрос того же домена, а куки-файлы устанавливаются непосредственно в интерфейсном источнике. Недостатки этого решения включают потенциал проблемы с производительностью из-за того, что другой сервер находится между (задержки) и куки-файлы должны быть установлены на двух источниках (войти дважды при прямом доступе к задней части). Настройка обратного прокси-сервера может быть выполнена с помощью nginx, apache или очень легко с помощью http-proxy-middleware
в узел.js:
var express = require('express');
var proxy = require('http-proxy-middleware');
var options = {
target: 'https://[server]',
changeOrigin: true,
secure: true
};
var exampleProxy = proxy(options);
var app = express();
app.use('/api', exampleProxy);
app.use(express.static(__dirname + "/public"));
app.listen(process.env.PORT || 8080);
Как вы можете прочитать здесь спецификация XHR и explictily запрещает чтение набор-печенье. Лучший способ сделать это-передать информацию в заголовке вместо файла cookie.