发布于2026-07-18 阅读(0)
扫一扫,手机访问
在使用 Lara vel Sanctum 配合 Vue 做前后端分离应用时,本地开发环境一切顺利,但一旦部署到生产环境的子域名(比如 `sub.my-domain.com`)下,登录成功后却依然被 `auth:sanctum` 中间件拦截,返回“未认证”错误。这个问题的根源,十有八九不是业务逻辑写错了,而是**跨域会话与 CSRF 令牌同步机制在握手环节出了岔子**。
具体症状表现为:前端调用 `/sanctum/csrf-cookie` 接口时,虽然返回了 204 状态码,但浏览器却没能成功写入 `XSRF-TOKEN` 和 `lara vel_session` 这两个关键的 Cookie。后续的请求自然也就无法携带认证凭据,导致认证链路断裂。不妨先看看,核心问题到底出在哪儿。
别急,按照下面的顺序逐一排查,多半能找到问题。这三处配置是典型的“牵一发而动全身”,必须保持一致。
这里的配置必须与你的部署环境严格匹配。很多新手容易忽略的一点是,如果服务器没有启用 HTTPS,却把 `secure` 选项设为 `true`,浏览器会直接拒绝存储任何 Cookie。这会导致整个认证链从第一步就断了。
'secure' => env('SESSION_SECURE_COOKIE', false), // 生产环境无 HTTPS 时,务必设为 false
'same_site' => 'lax', // 强烈建议显式指定为 'lax',避免使用 null 或 'strict',这能确保子域名间的 Cookie 正常发送
⚠️ 注意:如果 `APP_URL` 是 `http://` 开头,而 `secure: true`,那么 Cookie 根本不会被存储,问题就是这么直接。
`.env` 文件中的声明必须精确无误。这里有几个关键点,稍有不慎就会导致匹配失败。
SESSION_DRIVER=cookie SANCTUM_STATEFUL_DOMAINS=sub.my-domain.com SESSION_DOMAIN=.my-domain.com SESSION_LIFETIME=120 SESSION_SECURE_COOKIE=false
这个文件里的 `stateful` 配置,建议直接依赖环境变量,避免硬编码带来的冗余逻辑。很多坑都是从自动解析 `APP_URL` 开始的。
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,localhost:3000,127.0.0.1')),
✨ 建议删除原配置中那些通过 `sprintf` 拼接的冗余逻辑,比如自动解析 `APP_URL` 的代码。这很容易因为 URL 格式异常(比如带了 `http://`)而导致域名匹配失败。生产环境只需要确保 `.env` 文件中的 `SANCTUM_STATEFUL_DOMAINS` 值准确无误即可。
后端的配置搞定后,前端这边也得跟上。确保你的 Axios 全局配置已经启用了 `withCredentials`。
// axios.js 或 main.js 中 axios.defaults.withCredentials = true;
在登录流程中,必须严格按照顺序调用:
// 正确示例:先获取 CSRF Cookie,再发起登录请求
await axios.get('/sanctum/csrf-cookie', { withCredentials: true });
const res = await axios.post('/api/login', { email, password }, { withCredentials: true });
? 注意:`withCredentials: true` 必须在每个请求中显式传入,包括 `csrf-cookie` 和 `login` 这两个请求。否则,浏览器不会发送 Cookie,服务端无法建立会话,认证自然也就无从谈起。
配置完成后,可以用几个小技巧来验证是否生效:
完成上述配置后,Sanctum 就能正确识别子域名下的请求为“状态化”请求,自动绑定会话与 CSRF 令牌。至此,`auth:sanctum` 中间件应该就能稳定通过认证校验了。核心原则总结起来就一句话:**前端的凭据传递、后端的 Cookie 域策略、中间件的状态域配置,三者必须保持严格一致。** 这是排查此类问题的根本思路。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8