未设置 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-Age
和res.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?
为啥在使用 setRequestHeader 制作 xmlhttprequest 时无法设置 cookie 和 set-cookie 标头?