Почему Chrome не может устанавливать файлы cookie

Я получил ответ от моего сервера. Заголовки ответа содержат действительный Set-Cookie. Chrome Response/Cookies говорит, что у меня есть 1 файл cookie, хорошо. Но... Файл cookie не устанавливается в DevTools/Application/Cookies

/*
 My frontend on Vue
 I renamed 127.0.0.1 to www.example.com
 So running on www.example.com:80 or just www.example.com
*/
let response = await axios({
               method: 'post',
               url: 'http://127.0.0.1:3000/api/login', // my Node server on 3000 port   
               data: {
                   email : login,
                   password: password,
               },
            })
/*
 My backend part on Node.js+Express
 Running on localhost:3000 or 127.0.0.1:3000
 CookieParser() is setted
*/
let options = {
              maxAge: 345600000,
              httpOnly: true,
              path: '/',
            }

res
   .cookie('test', 'test', options)
   .cookie('access_token', token, options) //token contains a JWT string
   .send('');
/*
 Chrome Response Headers
*/
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Sun, 09 Feb 2020 08:52:22 GMT
ETag: W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"
Set-Cookie: test=test; Max-Age=345600; Path=/; Expires=Thu, 13 Feb 2020 08:52:22 GMT; HttpOnly
Set-Cookie: access_token=example; Max-Age=345600; Path=/; Expires=Thu, 13 Feb 2020 08:52:22 GMT; HttpOnly
X-Powered-By: Express
/*
 Chrome request headers
*/
Accept: application/json, text/plain, '*/*'
Accept-Encoding: gzip, deflate, br
Accept-Language: ru-RU,ru;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 45
Content-Type: application/json;charset=UTF-8
Host: 127.0.0.1:3000
Origin: http://www.example.com
Pragma: no-cache
Referer: http://www.example.com/
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36

Более того, я пытался использовать Microsoft Edge, но проблема не исчезла. Почему браузеры не могут устанавливать файлы cookie, если они знают о получении файлов cookie?

4 ответа

Решение

Если вы хотите немного почитать в общих чертах, я предлагаю вам поискать руководства по CORS (совместное использование ресурсов из разных источников) и, в частности, как устанавливать файлы cookie при использовании CORS.

Используя исходный код, вам нужно будет изменить его, чтобы установить withCredentials к true:

let response = await axios({
    method: 'post',
    url: 'http://127.0.0.1:3000/api/login', // my Node server on 3000 port   
    data: {
        email : login,
        password: password,
    },
    withCredentials: true
})

За кулисами это установит withCredentials флаг на XMLHttpRequest:

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials

После этого в консоли появятся ошибки CORS. Если вы исправите эти ошибки, вы сможете заставить его работать. Эти ошибки будут включать...

Во-первых, серверу нужно будет вернуть заголовок Access-Control-Allow-Credentials: true. Это также относится к предварительному запросу OPTIONS.

Во-вторых, вы сейчас используете Access-Control-Allow-Origin: *но это не разрешено для запросов с использованием учетных данных. Это должно бытьAccess-Control-Allow-Origin: http://www.example.com. То же самое и для предполетной подготовки.

На этом этапе файл cookie должен быть установлен в большинстве браузеров (подробнее об особенностях браузера позже).

Чтобы файлы cookie добавлялись в последующие запросы, вам также необходимо установить withCredentials: trueпо этим запросам. Остальные изменения заголовка, описанные выше, также должны быть применены. Файлы cookie не будут включены в предварительный запрос, а будут включены только в основной запрос.

Увидеть файлы cookie в инструментах разработчика браузера не совсем просто. Как правило, инструменты показывают только файлы cookie, установленные для того же источника, что и текущая страница, но не включают файлы cookie, установленные с помощью запросов CORS. Чтобы увидеть эти файлы cookie, вам нужно открыть другую вкладку браузера и указать URL-адрес, который начинается с того же источника, что и запрос CORS. Однако будьте осторожны, вам нужно выбрать URL-адрес, который не будет устанавливать файлы cookie, иначе это ничего не доказывает.

Другой способ проверить, какие файлы cookie установлены, - отправить другой запрос (с withCredentials) и посмотрите, какие файлы cookie будут отправлены.

Затем у нас есть проблемы, связанные с браузером...

В Safari очень сложно настроить файлы cookie для CORS. Если Safari является для вас целевым браузером, я предлагаю провести дополнительное исследование.

Во-вторых, Chrome 80 должен значительно изменить правила использования файлов cookie CORS. Видеть:

https://www.chromium.org/updates/same-site

Вы уже будете видеть предупреждения об этом на своей консоли в более старых версиях Chrome. Короче говоря, файлы cookie CORS необходимо будет обслуживатьhttps и установите директивы Secure а также SameSite=None.

Если вы используете Axios или Fetch - они по умолчанию не отправляют куки. Если вы пойдете и зайдете в инструменты dav - (вкладка приложения -> куки), вы должны их увидеть. это не проблема с хромами, а с тем, как вы пытаетесь отправить их обратно, в выборке вам нужно добавитьcredentials: 'include', объекту option, в аксиомах это {withCredentials: true}

Столкнулся с той же проблемой, что и у OP, оказалось, что моя довольно проста:

Нужно обратить внимание при использованииaxios, если вы используете этот синтаксис:axios.post()

Что я сделал не так:

      axios.post(
    "url",
    { withCredentials: true } // <- this is request body
);

Исправить:

      axios.post(
    "url",
    null,
    { withCredentials: true } // <- this is config
);

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

из официальной документации: https://www.npmjs.com/package/express-session


если вы используете cross-site origin and https безопасное соединение:

      session: {
   cookie: {
      maxAge: 1000*60*60*1,
      httpOnly: true, //set false if you want to change the cookie using JavaScipt
      secure: true,
      sameSite: 'none'
  }
}

и не забудьте установить: app.set('trust proxy', 1) используя экспресс js


иначе в localhost ты можешь использовать

      session: {
   cookie: {
      maxAge: 1000*60*60*1,
      httpOnly: true, //set false if you want to change the cookie using JavaScipt
      secure: false,
      sameSite: 'lax'
  }
}
Другие вопросы по тегам