浏览器无法存储Cookie:Index.js路由可行但Auth Controller失效问题
我试了各种办法在服务器端存储Cookie都没成功。在index.js的路由里设置Cookie时,浏览器能正常保存;但在Auth Controller里执行完全相同的操作,Cookie就是存不进去。Auth Controller是通过routes文件夹里的authRouter调用的,这个路由文件只负责定义端点和调用中间件。
INDEX.js
import "dotenv/config"; import "./helpers/init_mongodb.js"; import express from 'express'; import morgan from 'morgan'; import createError from "http-errors"; import cors from "cors"; import cookieParser from "cookie-parser"; import authRouter from "./routes/Auth.route.js"; (async () => { const app = express(); app.use(morgan("dev")); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(cookieParser()); app.use(cors()); app.use((req, res, next) => { res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE"); res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); res.setHeader("Access-Control-Allow-Credentials", true); next(); }) app.get("/", (req, res) => { res.send("WELCOME TO CODERS PARK"); }); app.use("/auth", authRouter); // HTTP ERRORS app.use((req, res, next) => { next(createError(404)); }); app.use((err, req, res, next) => { res.locals.message = err.message; res.locals.error = req.app.get("env") === "development" ? err : {}; res.status(err.status || 500); res.json({ error: { message: err.message } }); }); app.listen(process.env.PORT || 4000, () => { console.log(`Server is running on port ${process.env.PORT || 4000}`); }); } )();
AUTHCONTROLLER.js
import User from "../models/User.model.js"; import { generateToken } from "../helpers/jwt_helper.js"; import bcrypt from "bcrypt"; // handle Error const handleError = (err) => { console.log(err.message, err.code); let errors = { name: '', email: '', password: '' }; // not enter name if (err.message === "Please Enter Your Name") { errors.name = "Please Enter Your Name"; } // not enter both email and password if (err.message === "Please Enter Your Email and Password") { errors.email = "Please Enter Your Email"; errors.password = "Please Enter Your Password"; } // incorrect email if (err.message === 'incorrect email' || err.message === 'Incorrect Email') { errors.email = 'That email is not registered'; } // incorrect password if (err.message === 'incorrect password' || err.message === 'Incorrect Password') { errors.password = 'That password is incorrect'; } // duplicate error code if (err.code === 11000 || err.code === 11001) { errors.email = 'That email is already registered'; return errors; } // validation errors if (err.message?.includes('user validation failed') || err.message?.includes('User validation failed')) { Object.values(err.errors).forEach(({ properties }) => { errors[properties.path] = properties.message; }); } return errors; } const register = async (req, res, next) => { const { firstName, lastName, email, password } = req.body; console.log(req.body); const name = firstName + " " + lastName; try { if (!firstName || !lastName || firstName === "" || lastName === "") { throw new Error("Please Enter Your Name"); } const user = await User.create({ name, email, password }); res.status(201).json({ user: user.uid }); } catch (err) { res.status(500).send(handleError(err)); } } const login = async (req, res, next) => { const { email, password } = req.body; console.log(email, password); if (!email || !password || email === "" || password === "") { res.status(500).send(handleError("Please Enter Your Email and Password")); return; } try { const user = await User.findOne({ email }); if (user) { const auth = await bcrypt.compare(password, user.password); if (auth) { const token = generateToken(user.uid); console.log(token) res.cookie('jwt', token, { maxAge: 10000000 * 365, httpOnly: true }); // 1 year res.status(200).json({ user: user.uid }); return; } throw Error('incorrect password'); } else { throw Error('incorrect email'); } } catch (err) { res.status(500).send(handleError(err)); } } const logout = async (req, res, next) => { res.send('logout'); } export { register, login, logout };
问题根源及修复方案
1. CORS配置冲突
你同时用了app.use(cors())和自定义的CORS头设置,这会导致配置冲突。尤其是Access-Control-Allow-Origin设为*时,和Access-Control-Allow-Credentials: true完全不兼容——浏览器明确禁止通配符源同时开启凭证支持,这会直接导致Cookie无法被保存。
修复:
删掉自定义的CORS中间件,改用cors包的配置项统一设置:
// 替换原来的app.use(cors())和自定义CORS中间件 app.use(cors({ origin: "http://localhost:3000", // 改成你的前端实际域名,开发环境填本地地址 credentials: true, methods: ["GET", "POST", "PUT", "PATCH", "DELETE"], allowedHeaders: ["Content-Type", "Authorization"] }));
2. 前端请求必须携带凭证
前端发送登录请求时,必须开启凭证携带选项,否则服务器设置的Cookie会被浏览器忽略:
- Axios示例:
axios.post('/auth/login', { email, password }, { withCredentials: true })
- Fetch示例:
fetch('/auth/login', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) })
3. Cookie配置优化
你当前的Cookie有效期数值10000000 * 365过大,建议改成标准毫秒数(1年=31536000000毫秒),同时生产环境补充安全配置:
res.cookie('jwt', token, { maxAge: 1000 * 60 * 60 * 24 * 365, // 标准1年毫秒数 httpOnly: true, secure: process.env.NODE_ENV === 'production', // 生产环境开启HTTPS专属 sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax' // 跨域场景下需设为none });
4. 确认中间件顺序
确保cookie-parser和cors中间件在authRouter之前加载,你当前index.js的顺序是正确的,后续调整路由时别搞反就行。
内容的提问来源于stack exchange,提问作者Kartik Fulara
相关产品推荐
相关产品推荐

