首页 > 解决方案 > 带有 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:3000React 客户端运行的位置。

我尝试过的一些事情:

  1. secure:true用&secure:false的所有组合尝试所有sameSite:false&的组合sameSite:'strict'
  2. 将域设置为NULL或空字符串
  3. 试图随机改变路径

这是我在后端登录时设置 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;

我测试过的其他一些东西:

  1. 我已经仔细检查了双方的凭据是否都设置为 true。
  2. 我已确保身份验证周期在其他浏览器上运行。
  3. 当我在 http 而不是 https 上运行 React 时,我还确保身份验证周期在 Chrome 上有效
  4. 我还将我的自签名证书添加到本地计算机上的受信任根证书中。Chrome 不再向我显示警告但仍拒绝保存 cookie
  5. 如果我在禁用网络安全的情况下运行 Chrome 实例,我已确保身份验证周期有效。
  6. 我试图通过在地址栏中使用 127.0.0.1 而不是 localhost 来使其工作,但无济于事。
  7. 任何一方的控制台上都不会记录任何错误。

任何和所有的帮助将不胜感激

标签: reactjsexpressgoogle-chromecookiesmern

解决方案


Chrome 总是用 cookie 和 localStorage 做一些疯狂的事情......

从 chrome 80 开始,chrome 似乎会拒绝任何未专门设置的 cookie,SameSite=None并且Secure在使用跨站点请求时。该问题https://github.com/google/google-api-javascript-client/issues/561仍然开放并在那里进行讨论。我也认为在不设置的情况下使用 httpsSecure也会被拒绝。


推荐阅读