Laravel Sanctum 是官方轻量级认证方案,支持 SPA 的 Cookie Session 认证和移动端的 Token 认证。但在生产环境中,不少项目会遇到原本本地正常的接口突然返回 401 未认证的情况。这类问题大多与运行环境差异有关,而不是业务代码写错。

常见导致生产环境未认证的原因
- 生产域名与前端分离,SESSION_DOMAIN 未设置为共享根域名,导致认证 Cookie 无法写入。
- 启用了 HTTPS 但未配置 Secure Cookie,浏览器拒绝携带身份凭证。
- CORS 配置缺失,前端跨域请求未带 withCredentials,Session Cookie 不发往后端。
- API 路由未使用 auth:sanctum 中间件,或守卫配置错误。
检查并修复 Session 域配置
如果前端和后端不在同一子域,需要在 .env 中显式声明会话域名。例如前端为 app.ipipp.com,后端为 api.ipipp.com,则应配置如下:
# .env 生产环境配置示例 SESSION_DOMAIN=.ipipp.com SANCTUM_STATEFUL_DOMAINS=app.ipipp.com
确保 HTTPS 与 Cookie 安全属性
生产环境通常使用 HTTPS,Laravel 的 session 配置需开启 secure 选项,否则浏览器不会保存认证 Cookie:
<?php
// config/session.php 关键配置
return [
'secure' => env('SESSION_SECURE_COOKIE', true),
'http_only' => true,
'same_site' => 'lax',
];
前端请求必须携带凭证
使用 Axios 等工具调用后端接口时,需要开启 withCredentials,否则 Cookie 不会随请求发送:
import axios from 'axios';
axios.defaults.withCredentials = true;
axios.defaults.baseURL = 'https://api.ipipp.com';
// 登录后访问受保护接口
axios.get('/api/user')
.then(res => console.log(res.data))
.catch(err => console.error(err.response.status));
路由与中间件验证
确认受保护接口已应用 Sanctum 守卫,避免遗漏中间件导致直接放行或拒绝:
<?php
// routes/api.php
use IlluminateSupportFacadesRoute;
Route::middleware('auth:sanctum')->get('/user', function () {
return auth()->user();
});
使用 CSRF 保护的正确流程
SPA 认证前需先请求 CSRF Cookie,并在后续请求头中携带 X-XSRF-TOKEN。Sanctum 依赖此机制防止跨站请求:
// 先获取 csrf cookie
await axios.get('/sanctum/csrf-cookie');
// 再发起登录
await axios.post('/login', {
email: 'test@ipipp.com',
password: 'secret'
});
快速排查清单
| 排查项 | 正确示例 |
|---|---|
| SESSION_DOMAIN | .ipipp.com |
| SANCTUM_STATEFUL_DOMAINS | app.ipipp.com |
| 前端 withCredentials | true |
| 路由中间件 | auth:sanctum |
总结
生产环境 Sanctum 未认证问题本质是环境配置与请求链路不一致。按以上步骤核对域名、Cookie 安全、CORS 与中间件,基本可以解决绝大多数部署后鉴权失效的情况。