我正在构建一个 MERN 博客应用程序。最初在部署到 vercel 之前运行良好。 服务器托管在 http://localhost:3000 上,客户端 React 部分托管在 http://localhost:8000 上。 服务器文件部署在 vercel 上。 其他路由工作正常,但需要 cookie(令牌)的路由无法工作。 当我在请求标头中看到时,cookie 没有被发送。但是当我在 vercel 上部署之前执行此操作时,它也会将 cookie 发送到后端。 为什么会出错?
后端的 vercel url 是: https://blog-app-server-red.vercel.app/
前端代码(反应):
const getProfilePic = async ()=>{
try {
const response = await fetch('https://blog-app-server-red.vercel.app/user/'+userId , {
credentials : 'include',
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Credentials": true,
}
})
后端代码(express、mongo):
app.get('/user/:id' , async (req, res)=>{
try {
const {token} = req.cookies;
const {id} = req.params;
if(token){
jwt.verify(token , process.env.JWT_KEY , {} , async (err , info)=>{
if(err){
throw "Wrong Token ! Access Denied"
}
const user = await User.findById(id).select('-password');
res.status(200).json(user);
});
}
else{
res.status(400).json({error : "Unauthorized !!!"})
}
} catch (error) {
res.status(400).json({error});
}
})
CORS 中间件(后端):
app.use(cors({credentials : true , origin : 'http://localhost:3000'}));
当对 http://localhost:8000 (后端 api)执行相同操作时,它工作正常并且 cookie 也正在发送。 这是为什么?
当您的后端部署在 Vercel 上时,此问题似乎是由于 CORS 和 cookie 策略造成的。
尝试这些配置以确保 cookie 在服务器上正确发送,
const allowedOrigins = ['http://localhost:8000', 'https://your-frontend-domain.vercel.app'];
app.use(cors({
credentials: true,
origin: (origin, callback) => {
if (allowedOrigins.includes(origin) || !origin) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
}
}));
确保后端服务器端点设置的 cookie 具有要在跨源请求中发送的适当属性。您需要将
SameSite
属性设置为 None
并确保将 Secure
属性设置为 true
以实现安全上下文 (HTTPS)
res.cookie('token', token, {
httpOnly: true,
secure: true,
sameSite: 'None'
});
在你的前端代码上一切看起来都不错,添加 try-catch 进行错误处理会很好。
const getProfilePic = async () => {
try {
const response = await fetch('https://blog-app-server-red.vercel.app/user/' + userId, {
credentials: 'include',
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Credentials": true,
}
});
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
return data;
} catch (error) {
console.error('There was a problem with your fetch operation:', error);
}
};
仅当您使用会话时,请确保会话配置允许跨域 cookie,
app.use(session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: true,
cookie: {
secure: true, // Ensure this is true if using HTTPS
sameSite: 'None'
}
}));
在生产中,您的前端和后端都应该通过 HTTPS 提供服务。通过非安全连接发送时,浏览器会阻止标记为
Secure
的 cookie。
使用浏览器的开发者工具验证 cookie 是否已正确设置和发送。检查“应用程序”>“Cookie”以确保令牌存储正确,并在“网络”>“标头”下检查 cookie 是否包含在请求中。