NodeJs后端与React前端远程环境Cookie参数设置异常排查
问题描述
- 需求:后端在Cookie中设置并修改名为
Myparameter的参数 - 现象:
- Postman测试时,本地和远程环境均可正常设置Cookie
- 浏览器页面操作时,仅本地环境生效,远程后端无法更新Cookie中的
Myparameter
- 补充:浏览器控制台网络标签可见Cookie,但仅本地环境的Storage Cookie中显示;尝试Postman生成的Fetch代码,仍无效
后端代码(Node.js + Express)
var express = require('express'); const cookieParser = require('cookie-parser'); var cors = require('cors'); let bodyParser = require('body-parser'); const sessions = require('express-session'); var app = express(); app.use(cookieParser()); app.use(cors({ origin: ['http://localhost:3000', 'http://REMOTE_IP:3000'], credentials: true, exposedHeaders: ["set-cookie"] })); app.use(express.json()); //app.set("trust proxy", 1); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(express.urlencoded({ extended: true })); //const oneDay = 1000 * 60 * 60 * 24; const two_min_session = 1000 * 120; app.use(session1 = sessions({ name: "cookie_session1", secret: "fgydsanffdsafdsf456845dsfaf4651315641", cookie: { maxAge: two_min_session, httpOnly: true, sameSite: 'strict', secure: false, }, resave: true, saveUninitialized: true, sameSite: 'none', })); var one_more_cookie = function (req, res) { console.log(Date(), "Req", req.body, req.params, req.cookie); res.header('Access-Control-Allow-Origin', 'http://localhost:3000'); res.header('Access-Control-Allow-Credentials', 'true'); res.header('Access-Control-Expose-Headers', 'date, etag, access-control-allow-origin, access-control-allow-credentials'); res.cookie('refresh_token', 'refresh_token', { maxAge: 30 * 24 * 60 * 60 * 1000, httpOnly: true, sameSite: 'none', path: '*/*' }); res.status(200).json("Cookie Sent from Backend"); }; app.post('/api/cookie', cookieParser(), one_more_cookie); app.post('/api/logincookie', cookieParser(), (req, res) => { console.log("Cookies", req.cookies); console.log(req.session, req.session); res.status(200).send({ 'Reading req': 'Reading req' }); }); app.post('/api/setcookie', cookieParser(), (req, res) => { console.log("Session Before", req.session); console.log("Cookies Before", req.cookies); req.session.Myparameter = "Check"; console.log("Session After", req.session); console.log("Cookies After", req.cookies); res.status(200).json({ 'cookie': 'set' }); }); const port = process.env.PORT || 3001; app.listen(port, function () { console.log('Your app is listening on port ' + port) });
前端代码(React + Axios)
const checkCookie = function () { const data = axios.post('http://REMOTE_IP:3000/api/logincookie', { withCredentials: true }); } const setCookie = function () { const data = axios.post('http://REMOTE_IP:3000/api/setcookie', { withCredentials: true }); } const getCookie = async () => { try { const { data } = await axios.post('http://REMOTE_IP:3000/api/cookie', { withCredentials: true }); } catch (error) { console.log(error); } }
解决方案
1. 修复Session Cookie的跨域配置冲突
远程环境浏览器对跨域Cookie限制更严格,当前Session配置存在冗余和错误:
- 将
cookie.sameSite改为'none'(跨域场景必须设置),删除外层冗余的sameSite: 'none' - 生产环境(HTTPS)下开启
secure: true,本地HTTP环境保持false - 优化
resave和saveUninitialized参数,减少不必要的Session存储
修改后的Session配置:
app.use(sessions({ name: "cookie_session1", secret: "fgydsanffdsafdsf456845dsfaf4651315641", cookie: { maxAge: two_min_session, httpOnly: true, sameSite: 'none', secure: process.env.NODE_ENV === 'production' ? true : false, }, resave: false, saveUninitialized: false, }));
2. 统一CORS配置,删除硬编码Header
one_more_cookie函数中硬编码的Access-Control-Allow-Origin会与CORS中间件冲突,直接删除手动设置的Header,同时修正req.cookie为req.cookies,调整Cookie路径为'/':
var one_more_cookie = function (req, res) { console.log(Date(), "Req", req.body, req.params, req.cookies); res.cookie('refresh_token', 'refresh_token', { maxAge: 30 * 24 * 60 * 60 * 1000, httpOnly: true, sameSite: 'none', secure: process.env.NODE_ENV === 'production' ? true : false, path: '/' }); res.status(200).json("Cookie Sent from Backend"); };
3. 修正Axios的withCredentials配置位置
当前代码将withCredentials放在请求data中,需调整为请求config参数:
const checkCookie = function () { const data = axios.post('http://REMOTE_IP:3000/api/logincookie', {}, { withCredentials: true }); } const setCookie = function () { const data = axios.post('http://REMOTE_IP:3000/api/setcookie', {}, { withCredentials: true }); } const getCookie = async () => { try { const { data } = await axios.post('http://REMOTE_IP:3000/api/cookie', {}, { withCredentials: true }); } catch (error) { console.log(error); } }
4. 启用信任代理(远程环境用反向代理时)
如果后端部署在Nginx等反向代理后,开启trust proxy让Express正确识别请求协议:
app.set("trust proxy", 1);
5. 验证Session参数是否生效
Myparameter存储在服务器端Session中,浏览器仅保存Session ID Cookie,可在/api/logincookie接口返回该参数验证:
app.post('/api/logincookie', cookieParser(), (req, res) => { console.log("Cookies", req.cookies); console.log("Session", req.session); res.status(200).send({ 'Reading req': 'Reading req', 'Myparameter': req.session.Myparameter }); });
内容的提问来源于stack exchange,提问作者Nuno C
相关产品推荐
相关产品推荐

