You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部署Azure后端与前端后浏览器无法设置JWT Cookie求助

部署到Azure后浏览器无法设置JWT Cookie的解决方案

问题背景

开发博客网站时,通过Cookie存储JWT Token实现用户认证,本地环境运行正常,但后端部署到Azure虚拟机(Azure VM)、前端部署到Azure应用服务(Azure App Services)后,浏览器无法设置Cookie。

相关代码

index.js

const express = require("express");
const dbconnection = require("./database/dbconnect");
const authRoute = require("./routes/authRoutes.js");
const bodyParser = require("body-parser");
const userRoute = require("./routes/userRoute.js");
const blogRoute = require("./routes/blogRoute.js");
const cookieParser = require("cookie-parser");
const cors = require("cors");
const PORT = 8000;

dbconnection();

const app = express();

app.use(bodyParser.json({ extended: true }));

// app.setHeader("Access-Control-Allow-Credentials", "true");

app.use((req, res, next) => {
// Set CORS headers
res.header("Access-Control-Allow-Origin", process.env.FRONTEND_URL); // Replace with your frontend domain
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
res.header("Access-Control-Allow-Credentials", "true"); // Allow credentials (cookies, etc.)
// Pass to next layer of middleware
next();
});

app.use(bodyParser.urlencoded({ extended: true }));

app.use(cookieParser());

app.use("/", authRoute);
app.use("/user", userRoute);
app.use("/blog", blogRoute);

app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});

login.js

const User = require("../database/model/user");
const bcrypt = require("bcrypt");
const env = require("dotenv");
const { createSecretToken } = require("../tokenGeneration/generateToken");
env.config();

const login = async (req, res) => {
const { email, password } = req.body;
if (!(email && password)) {
return res.status(400).json({ message: "All input is required" });
}
const user = await User.findOne({ email });
if (!(user && (await bcrypt.compare(password, user.password)))) {
return res.status(404).json({ message: "Invalid credentials" });
}
const token = createSecretToken(user._id);
console.log(token)
res.cookie("token", token, {
domain:'.bloggle-vista.azurewebsites.net',
path: "/",
httpOnly: true,
secure: true,
sameSite:"None"
});
res.json({ token });
};

module.exports = login;

修复方案

1. 改用CORS包规范配置跨域

手动设置CORS Header容易忽略OPTIONS预请求处理,直接使用cors中间件更可靠:

替换index.js中手动设置Header的中间件:

// 删除原来的手动CORS Header中间件,替换为以下代码
app.use(cors({
  origin: process.env.FRONTEND_URL,
  credentials: true,
  allowedHeaders: ["Content-Type", "Authorization"],
  methods: ["GET", "POST", "PUT", "DELETE"]
}));

cors包会自动处理OPTIONS请求的响应头,避免跨域配置冲突。

2. 修正Cookie的Domain和Secure配置

当前Cookie的Domain设置为前端域名,这是错误的,Cookie的Domain必须与后端服务的域名/IP一致:

修改login.js中的Cookie配置:

res.cookie("token", token, {
  // 移除错误的前端Domain,让浏览器自动绑定后端请求域名
  // domain:'.bloggle-vista.azurewebsites.net',
  path: "/",
  httpOnly: true,
  // 仅生产环境启用Secure(要求HTTPS)
  secure: process.env.NODE_ENV === "production",
  // 生产环境用None,本地用Lax
  sameSite: process.env.NODE_ENV === "production" ? "None" : "Lax"
});

如果后端使用Azure VM的公网IP,也可以显式设置domain: "你的VM公网IP",但留空让浏览器自动处理更灵活。另外,若后端未配置HTTPS,secure: true会导致Cookie无法设置,需先为Azure VM配置SSL证书(比如用NGINX+Let's Encrypt)。

3. 确保Azure VM网络配置正确

  • 在Azure VM的**网络安全组(NSG)**中添加入站规则,开放8000端口,允许前端域名的访问。
  • 若后端使用HTTP,需将secure设为false,但生产环境强烈建议配置HTTPS。

4. 前端请求必须携带Credentials

前端发起登录请求时,需开启withCredentials(以Axios为例):

axios.post(`${BACKEND_URL}/login`, { email, password }, { withCredentials: true })

只有前端请求携带Credentials,浏览器才会保存后端设置的Cookie。

5. 验证环境变量配置

确保Azure VM的环境变量中FRONTEND_URL设置为前端完整域名(比如https://bloggle-vista.azurewebsites.net),必须包含https://协议前缀。

内容的提问来源于stack exchange,提问作者Sahil Bisht

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 12:19:53