未设置 Set-Cookie 标头中的 Cookie

Posted

技术标签:

【中文标题】未设置 Set-Cookie 标头中的 Cookie【英文标题】:Cookie in Set-Cookie header not being set 【发布时间】:2020-08-16 16:30:18 【问题描述】:

我正在使用 axios 从 reactjs 客户端向 node.js 服务器发送请求,如下所示。

import axios from 'axios';

const apiClient = axios.create(
  withCredentials: true,
  baseURL: 'http://localhost:8080'
);

async function(payload) 
  try 
    debugger;
    let result = await apiClient.post('/auth/signup/', payload);
    debugger;
    return result;
   catch (error) 
    debugger;
    throw error;
  

node.js 端点在响应中设置一个 cookie,如下所示。

const express = require('express');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser')
const cors = require('cors');
const jwt = require('jsonwebtoken');

router.use(bodyParser.json());
router.use(bodyParser.urlencoded( extended: true ));
router.use(cors( origin: 'http://localhost:3000', credentials: true, exposedHeaders: ['Set-Cookie', 'Date', 'ETag'] ));
router.use(cookieParser());


router.post('/signup', async (req, res, next) => 
  debugger;
  let database = req.app.locals.database;
  try 
    let user = await database.findByUsername(req.body.username);
    let token = await jwt.sign(username: user.username, config.secret, expiresIn: "15m");
    res.cookie('jwt',  token, 
      maxAge: 900,
    );
   catch (error) 
    debugger;
    return res.status(503).send( auth: false, message: 'Database error.' );
  
);

响应的 Set-Cookie 标头包含预期的 cookie。

但是,Chrome 似乎没有设置 cookie,因为我在开发者控制台的应用程序窗口中看不到 cookie。

我查看了以下问题的答案,其中提到在 axios 配置中设置 withCredentials: true 并且在 node.js 中没有为 cors 使用通配符来源,但我已经在做这两件事了。

Set-Cookie header not setting cookie in Chrome

Set cookies for cross origin requests

关于未设置 cookie 的原因以及如何解决此问题的任何想法?

【问题讨论】:

好问题。插入图片,点赞。 【参考方案1】:

虽然您将客户端和服务器托管在与http://localhost 相同的域中,但您的端口不同,因此此处的同源策略失败。您可以查看https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy。

因此,您发出 CORS 请求,在当前浏览器的开发人员工具中检查您的网络选项卡,您可能会在客户端向您的服务器发送 POST 请求之前看到一个预检请求 OPTIONS

服务器必须指定headers来接受你下一个请求的来源——来自http://localhost:8000的POST请求,方法为POST,你可以参考https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request

HTTP/1.1 204 No Content
Connection: keep-alive
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: POST // Your next request will use POST method
Access-Control-Max-Age: 86400
Access-Control-Allow-Credentials: true // cookies accepted

添加:

Set-Cookie 中,Max-Age 必须是 non-zero digit。根据RFC doc四舍五入为整数。对于 express.js,cookie 的 `maxAge 属性在 miliseconds 的范围内

解决方案将maxAge属性设置为second * 1000

    res.cookie('jwt',  token, 
      maxAge: 10000,
    );

【讨论】:

查看express的cors中间件即可。它似乎完成了在飞行前响应中设置 CORS 配置的所有工作。现在,我对响应的样子非常感兴趣。 无法再根据以下来源在 Chrome DevTools 中查看预检请求:httptoolkit.tech/blog/chrome-79-doesnt-show-cors-preflight。我也不太确定你在说我应该在预检请求/响应中寻找什么。你能澄清一下吗? 从屏幕上看,服务器响应的 HTTP cookie 的值似乎没有问题。然后,检查Set-Cookie 中的Max-Age,这可能是问题所在,因为 IIRC 该值必须是非零数字。 谢谢,Max-Age 值为 0 确实是问题所在。我以为我在节点中设置了Max-Ageres.cookie('jwt', token, maxAge: 900);,但是查看Set-Cookie 标头,Max-Age 为0。虽然节点中cookie 选项中的maxAge 属性以毫秒为单位,但@ Set-Cookie 标头中的 987654346@ 以秒为单位,因此我的 900 毫秒值被四舍五入为 0 秒。将您评论中的信息添加到您的答案中,我会接受。【参考方案2】:

这是我对类似问题https://***.com/a/62821342/8479303的回答的转贴


在我的情况下,网络面板显示响应具有“Set-Cookie”标头,但在 axios 中标头不会显示,并且正在设置 cookie。

对我来说,分辨率是设置Access-Control-Expose-Headers 标头。

为了解释,this comment 在 axios 存储库中的一个问题上,我被定向到了这个 person's notes,这导致我设置了 Access-Control-Expose-Headers header——现在 cookie 已在客户端中正确设置。

因此,在 Express.js 中,我必须将 exposedHeaders 选项添加到我的 cors 中间件:

const corsOptions = 
  //To allow requests from client
  origin: [
    "http://localhost:3001",
    "http://127.0.0.1",
    "http://104.142.122.231",
  ],
  credentials: true,
  exposedHeaders: ["set-cookie"],
;

...

app.use("/", cors(corsOptions), router);

同样重要的是,在 axios 方面,我使用 withCredentials 配置来跟踪我想要包含 cookie 的 axios 请求。

前/

const  data  = await api.get("/workouts",  withCredentials: true );

【讨论】:

exposedHeaders: ["set-cookie"] 在前端使用 Axios 时似乎很关键

以上是关于未设置 Set-Cookie 标头中的 Cookie的主要内容,如果未能解决你的问题,请参考以下文章

Set-Cookie 标头未出现在 Google Chrome 中

Owin cookie身份验证设置cookie未保存在浏览器中

为啥浏览器会忽略 set-cookie 标头,并且未使用 fetch 从 Ajax 调用中保存 cookie?

从打字稿中的 Set-Cookie 标头中获取 jwt 值

在响应标头中使用 apollo,cookie 但未设置

为啥在使用 setRequestHeader 制作 xmlhttprequest 时无法设置 cookie 和 set-cookie 标头?