本地开发时,前端跑在
127.0.0.1:8080,后端在7001端口——看似简单,但一涉及登录态(Cookie),跨域就成了“拦路虎”。
很多同学在搭建前后端分离项目时,会遇到这样一个典型场景:
- 前端 Vue 应用运行在
http://127.0.0.1:8080 - 后端 Egg.js 服务运行在
http://127.0.0.1:7001 - 首次访问主页 → 提示登录 → 提交账号密码 → 后端设置 Cookie → 下次自动携带 Cookie 实现“已登录”状态
听起来很合理,但实际开发中却频频报错:Cookie 没带上、后端读不到、浏览器显示 “Provisional headers are shown”……
今天,我们就来彻底梳理这个流程,并解决三大核心问题!
🧭 一、正确设计:登录态如何流转?
正常流程应为:
- 首次 GET 请求(
/)
→ 后端检查无 Cookie → 返回{ code: 401, msg: '请登录' }
→ 前端弹出登录框 - 用户 POST 登录(
/login)
→ 前端发送用户名/密码
→ 后端验证成功 → 设置 Cookie(含用户 ID) → 返回{ code: 200 } - 后续请求自动携带 Cookie
→ 浏览器自动在请求头中带上Cookie: userId=xxx
→ 后端读取 Cookie → 识别用户 → 返回个性化内容
✅ 关键点:Cookie 必须在跨域场景下正确设置 + 正确携带 + 正确读取
⚠️ 二、三大高频问题 & 解决方案
❌ 问题 1:跨域时 Cookie 被浏览器屏蔽
现象:后端明明设置了 Set-Cookie,但浏览器 DevTools 的 Application → Cookies 里看不到。
原因:
默认情况下,跨域请求不会携带 Cookie,即使服务器返回了 Set-Cookie,浏览器也会忽略。
解决方案:
✅ 后端(Egg.js)配置 CORS 支持凭证
安装 egg-cors 插件:
npm i egg-cors
在 config/plugin.js 中启用:
exports.cors = {
enable: true,
package: 'egg-cors',
};
在 config/config.default.js 中配置:
config.security = {
csrf: { enable: false }, // 开发阶段可关闭,生产务必开启
};
config.cors = {
origin: 'http://127.0.0.1:8080', // ⚠️ 必须是具体地址,不能为 '*'
credentials: true, // 允许携带 Cookie
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH',
};
🔥 重点:
origin不能写*!当credentials: true时,浏览器要求Access-Control-Allow-Origin必须是精确匹配的源(如http://127.0.0.1:8080)- 不要混用
localhost和127.0.0.1!它们在浏览器中被视为不同源。建议统一使用127.0.0.1
✅ 前端(Vue/Axios)开启凭证
// axios 全局配置
axios.defaults.withCredentials = true;
// 或单次请求
axios.post('http://127.0.0.1:7001/login', data, {
withCredentials: true
});
❌ 问题 2:后端 setCookie 了,但 ctx.cookies.get() 返回 undefined
现象:抓包看到请求头有 Cookie: userId=abc,但 Egg.js 里 ctx.cookies.get('userId') 却是 undefined。
原因:
你在 set 时加了选项(如 httpOnly: true),但 get 时没传相同参数!
正确做法:
// 设置 Cookie(带选项)
ctx.cookies.set('userId', '123', {
httpOnly: true,
signed: false,
maxAge: 24 * 60 * 60 * 1000, // 1天
});
// 读取时必须传入相同选项!
const userId = ctx.cookies.get('userId', {
signed: false, // ⚠️ 必须一致
});
💡 默认
signed: true,如果你没用 Egg 的 cookie 签名机制,记得显式设为false。
❌ 问题 3:DevTools 显示 “Provisional headers are shown”
现象:Network 面板中请求头显示灰色,并提示 “Provisional headers are shown”。
真相:
这不是错误!这是 Chrome 的一种安全提示,表示“这些 headers 是浏览器预估的,可能与实际发送的不同”。
常见触发场景:
- 页面刚加载,尚未发出真实请求(如 prefetch)
- 请求被重定向或取消
- 首次启动服务 + 首次访问(缓存未建立)
是否影响功能?
→ 如果你能收到正确响应(如 200、Cookie 设置成功),那就完全不用管它!
→ 它只是 DevTools 的 UI 提示,不代表请求失败。
✅ 验证方法:看 Response Headers 是否有
Set-Cookie,Application → Cookies 是否有值。
🛠️ 三、完整代码参考(Egg.js + Vue)
后端:登录接口示例
// app/controller/user.js
async login() {
const { ctx } = this;
const { username, password } = ctx.request.body;
// 简单验证(实际应查数据库)
if (username === 'admin' && password === '123456') {
ctx.cookies.set('userId', 'U1001', {
httpOnly: true,
signed: false,
maxAge: 24 * 60 * 60 * 1000,
});
ctx.body = { code: 200, msg: '登录成功' };
} else {
ctx.status = 401;
ctx.body = { code: 401, msg: '账号或密码错误' };
}
}
前端:Axios 配置
// main.js 或 api.js
import axios from 'axios';
axios.defaults.baseURL = 'http://127.0.0.1:7001';
axios.defaults.withCredentials = true; // 关键!
🌟 结语
跨域 + Cookie 是前后端分离开发中的经典难题,但只要记住三点:
- CORS 配置必须精确指定 origin,不能用
* - 前端请求必须带
withCredentials: true - Egg.js 读写 Cookie 参数要一致
搞定这些,登录态就能稳稳传递!
细节决定成败,调试就是修“边界条件”的过程。














暂无评论内容