为什么使用Laravel+Sanctum时会出现CSRF令牌不匹配错误?
修复方案如下
1. 前端代码问题修复
你现有的login函数存在两处错误:
- 没有返回
post请求的Promise,导致外部调用时无法拿到登录请求的响应 - 不需要手动对请求参数执行
JSON.stringify,Axios会自动将对象序列化为JSON格式
修复后的代码:
const apiClient = axios.create({ baseURL: `http://localhost:8000`, withCredentials: true, }); // 该配置可省略,Axios发送POST JSON请求时会自动携带对应Content-Type let config = { headers: { 'Content-Type': 'application/json' }, } export async function login(credentials: LoginCredentials) { return apiClient.get('sanctum/csrf-cookie', config).then(response => { // 新增return返回登录请求的Promise,去掉JSON.stringify return apiClient.post('/api/v1/login', credentials); }); }
2. SESSION_DOMAIN配置修复
你当前的SESSION_DOMAIN配置完全错误:
- 不能携带
http://协议前缀 - 不能指定前端端口3000,Session是后端生成的,domain需要配置为后端服务所在的根域
- 同域名不同端口场景下,配置为
.localhost即可跨端口共享Cookie
将.env文件中的SESSION_DOMAIN修改为:
SESSION_DOMAIN=.localhost
3. Sanctum stateful配置清理
stateful配置仅需要填写域名+端口,不需要填写具体路径,删除多余的localhost:3000/api/v1/login条目,修复后:
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( '%s%s', 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : '' ))),
4. API中间件组冗余配置删除
EnsureFrontendRequestsAreStateful中间件已经自动封装了会话启动、CSRF校验等逻辑,手动重复添加会导致逻辑冲突,修复后的api中间件配置:
'api' => [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ],
5. CORS配置优化
带凭据的跨域请求不允许allowed_origins设为*,部分浏览器会直接拦截该类请求,修改为明确的前端地址:
'allowed_origins' => ['http://localhost:3000'],
所有配置修改完成后,清空Laravel缓存再重试:
php artisan config:clear php artisan route:clear
内容的提问来源于stack exchange,提问作者Patrick Obafemi
相关产品推荐
相关产品推荐

