HttpOnly cookie 出现在响应 header 中,但未保存到浏览器

HttpOnly cookie appears in response header but is not being saved to the browser

我最近构建了一个简单的 real-time 聊天应用程序,前端使用 Nextjs,后端使用 Express。前端部署在vercel上,后端部署在heroku上。当用户登录应用程序时,后端会生成一个 jwt 令牌,然后通过 HttpOnly cookie 将其发送回前端。这是上述响应的代码:

 const authenticate = async (req, res, next) => {
  userService
    .authenticate(req)
    .then((user) => {
      const { token, ...userInfo } = user;
      res
        .setHeader(
          "Set-Cookie",
          cookie.serialize("token", token, {
            httpOnly: true,
            secure: process.env.NODE_ENV !== "development",
            maxAge: 60 * 60 * 24,
            sameSite: "none",
            path: "/",
          })
        )
        .status(200)
        .json(userInfo);
    })
    .catch(next);
};

身份验证后,对后端的每个后续请求都应该发送令牌以确保用户已登录。例如,这是发送到服务器以获取已登录用户与另一个用户之间的聊天的请求用户。

const getChat = async (id) => {
  const identification = id;
  const response = await axios.get(
    `<SERVER_URL>/chats/chat/${identification}`,
    { withCredentials: true }
  );

  return response;
};

在开发中,前端为 localhost:3000,后端为 localhost:4000,一切正常。但是,当我将前端部署到 vercel 并将后端部署到 heroku 时,浏览器根本拒绝保存 cookie!发送身份验证请求后,jwt 令牌出现在响应 header 中,但未保存到浏览器。我已经尝试了所有我能想到的方法,包括更改 cookie 参数,但我无法让它工作。我很确定我在后端也正确配置了 cors,以及 cookie-parser 模块:


const cors = require("cors");
const cookieParser = require("cookie-parser");

app.use(
  cors({
    origin: "<CLIENT_URL>",
    credentials: true,
  })

app.use(cookieParser());

感谢您抽出宝贵时间阅读本文,如有任何帮助,我们将不胜感激!如果我没有详细说明,我深表歉意,这是我第一次 post 在这里,我仍在努力学习网站的正确礼仪!

HttpOnly 不能在客户端读取或写入,但是当第一个 HttpOnly 通过请求发送时,同源的其他请求可以访问后端的 coockies,但你应该像这样在 Next.js 中请求。 Next.js 使用提取:

        const req = await fetch("http://localhost:7000/api/auth/login", {
      method: "POST",
      credentials: "include",
      headers: {
        "Content-Type": "application/json",
        "Access-Control-Allow-Credentials": true,
      },
      body: JSON.stringify({
        email: formData.get("email"),
        password: formData.get("password"),
      }),
    });
    const data = await req.json();

然后在后端你可以通过 coockie-parser 读取 cookie server.js:

const cookieParser = require("cookie-parser");
app.use(coockieParser());
route.post('/login',(req,res) => {
  if(user){
       res
  .cookie("access_token", newToken, {
    httpOnly: true,
    secure: process.env.NODE_ENV === "production" ? true : false,
  })
  .status(200)
  .json({ ok: true, payload: data });
 }
})

现在您可以在其他路由中读取此cookie,但确定过期时间。