商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Laravel Sanctum 认证失败:解决生产环境下的未认证问题

Laravel Sanctum 认证失败:解决生产环境下的未认证问题

  发布于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。后续的请求自然也就无法携带认证凭据,导致认证链路断裂。不妨先看看,核心问题到底出在哪儿。

关键配置修复清单

别急,按照下面的顺序逐一排查,多半能找到问题。这三处配置是典型的“牵一发而动全身”,必须保持一致。

1. 会话安全策略:`config/session.php`

这里的配置必须与你的部署环境严格匹配。很多新手容易忽略的一点是,如果服务器没有启用 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 根本不会被存储,问题就是这么直接。

2. 环境变量:`.env` 文件

`.env` 文件中的声明必须精确无误。这里有几个关键点,稍有不慎就会导致匹配失败。

SESSION_DRIVER=cookie
SANCTUM_STATEFUL_DOMAINS=sub.my-domain.com
SESSION_DOMAIN=.my-domain.com
SESSION_LIFETIME=120
SESSION_SECURE_COOKIE=false
  • `SANCTUM_STATEFUL_DOMAINS`:只填写子域名主体,比如 `sub.my-domain.com`。切记不要加上协议头(`http://`)、端口号或者通配符(`*`)。
  • `SESSION_DOMAIN`:必须以点号开头,例如 `.my-domain.com`。这表示该 Cookie 对 `my-domain.com` 及其所有子域名(如 `sub.my-domain.com`、`api.my-domain.com`)都有效。
  • `SESSION_SECURE_COOKIE`:在 HTTP 环境下,必须设为 `false`。只有在确认启用了 HTTPS 时,才能改为 `true`。

3. Sanctum 配置:`config/sanctum.php`

这个文件里的 `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,服务端无法建立会话,认证自然也就无从谈起。

验证与调试技巧

配置完成后,可以用几个小技巧来验证是否生效:

  • 打开浏览器开发者工具,切换到 **Application** 标签页下的 **Cookies**。确认访问 `/sanctum/csrf-cookie` 后,是否成功写入了 `XSRF-TOKEN` 和 `lara vel_session` 这两个 Cookie,并且它们的 `Domain` 列显示为 `.my-domain.com`。
  • 检查响应头中的 `Set-Cookie` 字段,看是否包含 `Domain=.my-domain.com; Path=/; Secure; HttpOnly; SameSite=Lax` 这些信息。注意,`Secure` 标志只在 HTTPS 环境下才会出现。
  • 最后,别忘了运行 `php artisan config:clear && php artisan cache:clear` 来清除配置缓存,确保新的配置生效。

完成上述配置后,Sanctum 就能正确识别子域名下的请求为“状态化”请求,自动绑定会话与 CSRF 令牌。至此,`auth:sanctum` 中间件应该就能稳定通过认证校验了。核心原则总结起来就一句话:**前端的凭据传递、后端的 Cookie 域策略、中间件的状态域配置,三者必须保持严格一致。** 这是排查此类问题的根本思路。

本文转载于:https://www.php.cn/faq/2344126.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注