reactjs - 带有 https 连接的 MERN 堆栈无法在 Chrome 上设置 cookie,但在所有其他浏览器上设置它们
问题描述
我正在开发一个典型的 MERN 应用程序,并且我已经完成了身份验证周期。我的 NodeJS/Express 后端使用“express-session”和“connect-mongodb-connection”来创建和处理会话。React 前端使用“axios”与 API 进行通信。身份验证周期适用于除 Chrome 之外的所有浏览器。对于所有其他浏览器,在 MongoDB 中成功创建了一个会话,在浏览器中设置了 cookie,我成功登录到一个会话中。
但是在使用 Chrome 进行测试时,除了设置 cookie 的部分之外,一切都运行良好。我在一天的时间里对此进行了严格的测试,我可以将 cookie 追踪到它从后端发送的位置。但 Chrome 拒绝保存 cookie。
这是我维护会话的代码:
服务器/app.js
var store = new MongoDBStore({
uri: DB,
collection: 'sessions'
});
// Catch errors
store.on('error', function (error) {
console.log(error);
});
app.use(require('express-session')({
secret: process.env.SESSION_SECRET,
saveUninitialized: false, // don't create session until something stored
resave: false, //don't save session if unmodified
store: store,
cookie: {
maxAge: parseInt(process.env.SESSION_LIFETIME), // 1 week
httpOnly: true,
secure: !(process.env.NODE_ENV === "development"),
sameSite: false
},
}));
//Mongo Session Logic End
app.enable('trust proxy');
// 1) GLOBAL MIDDLEWARES
// Implement CORS
app.use(cors({
origin: [
process.env.CLIENT_ORIGINS.split(',')
],
credentials: true,
exposedHeaders: ['set-cookie']
}));
CLIENT_ORIGINS
设置为https://localhost:3000
我的http://localhost:3000
React 客户端运行的位置。
我尝试过的一些事情:
secure:true
用&secure:false
的所有组合尝试所有sameSite:false
&的组合sameSite:'strict'
- 将域设置为
NULL
或空字符串 - 试图随机改变路径
这是我在后端登录时设置 cookie 的代码:
exports.signIn = async (req, res, next) => {
const { email, password } = req.body;
if (signedIn(req)) {
res.status(406).json('Already Signed In');
return;
}
const user = await User.findOne({ email: email });
if (!user) {
res.status(400).json('Please enter a correct email.');
return;
}
if (!(await user.matchPassword(password))) {
res.status(400).json('Please enter a correct password.');
return;
}
req.session.userId = user.id;
res.status(200).json({ msg: 'Signed In', user: user });
};
这是我使用 Axios 从 React 调用我的 API 的通用请求模型:
import axios from "axios";
import CONFIG from "../Services/Config";
axios.defaults.withCredentials = true;
const SERVER = CONFIG.SERVER + "/api";
let request = (method, extension, data = null, responseTypeFile = false) => {
//setting up headers
let config = {
headers: {
"Content-Type": "application/json",
},
};
// let token = localStorage["token"];
// if (token) {
// config.headers["Authorization"] = `Bearer ${token}`;
// }
//POST Requests
if (method === "post") {
// if (responseTypeFile) {
// config['responseType'] = 'blob'
// }
// console.log('request received file')
// console.log(data)
return axios.post(`${SERVER}/${extension}`, data, config);
}
//PUT Requests
else if (method === "put") {
return axios.put(`${SERVER}/${extension}`, data, config);
}
//GET Requests
else if (method === "get") {
if (data != null) {
return axios.get(`${SERVER}/${extension}/${data}`, config);
} else {
return axios.get(`${SERVER}/${extension}`, config);
}
}
//DELETE Requests
else if (method === "delete") {
if (data != null) {
return axios.delete(`${SERVER}/${extension}/${data}`, config);
} else {
return axios.delete(`${SERVER}/${extension}`, config);
}
}
};
export default request;
我测试过的其他一些东西:
- 我已经仔细检查了双方的凭据是否都设置为 true。
- 我已确保身份验证周期在其他浏览器上运行。
- 当我在 http 而不是 https 上运行 React 时,我还确保身份验证周期在 Chrome 上有效
- 我还将我的自签名证书添加到本地计算机上的受信任根证书中。Chrome 不再向我显示警告但仍拒绝保存 cookie
- 如果我在禁用网络安全的情况下运行 Chrome 实例,我已确保身份验证周期有效。
- 我试图通过在地址栏中使用 127.0.0.1 而不是 localhost 来使其工作,但无济于事。
- 任何一方的控制台上都不会记录任何错误。
任何和所有的帮助将不胜感激
解决方案
Chrome 总是用 cookie 和 localStorage 做一些疯狂的事情......
从 chrome 80 开始,chrome 似乎会拒绝任何未专门设置的 cookie,SameSite=None
并且Secure
在使用跨站点请求时。该问题https://github.com/google/google-api-javascript-client/issues/561仍然开放并在那里进行讨论。我也认为在不设置的情况下使用 httpsSecure
也会被拒绝。
推荐阅读
- nginx - Web 服务器和反向代理在同一个端口 nginx
- go - 简单程序死机,无法确定原因
- datatable - 有条件地格式化 Dash 数据表中的值 (Julia)
- azure-devops-server-2019 - 如何删除阻止删除存储库的文件锁?
- python - 使用 elif 打印用户是否访问过超过 2 个大洲但少于 6 个
- react-native - 更改为新路线时更改圆圈的动画大小
- c# - 单元测试 - 进程没有包 ID
- javascript - JSON正文上的正则表达式 - 兄弟
- javascript - 有人可以解释一下这段代码的第二部分吗?
- python - Python:保持和检查两个徽标是否相同与其方向无关的最佳方法