Laravel Sanctum跨域API认证失效问题及转用JWT解决
Laravel Sanctum跨域API认证失效问题排查与解决
问题背景
本地环境下用Laravel Sanctum做API认证完全正常,但把React部署到Firebase、Laravel部署到不同域名后,API请求直接返回401错误。现有配置如下:
app/Http/Kernel.php
protected $middlewareGroups = [ 'api' => [ \Fruitcake\Cors\HandleCors::class, // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];
config/cors.php
'paths' => ['api/*', 'sanctum/csrf-cookie'], 'allowed_methods' => ['*'], 'allowed_origins' => ['http://localhost:3000', 'https://example.web.app'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true,
试过查资料、问ChatGPT都没解决,一度以为Sanctum不支持跨域API授权,差点转用JWT认证。
核心问题澄清
Sanctum完全支持跨域API认证,你的问题出在几个关键配置缺失上:
- 注释掉了
EnsureFrontendRequestsAreStateful中间件——这是Sanctum处理跨域有状态请求的核心,没它Cookie根本没法正常传递和验证 - 没把前端域名加入Sanctum的信任列表
- Axios可能没正确携带凭证
修复步骤
1. 恢复核心中间件
修改app/Http/Kernel.php的api中间件组,取消EnsureFrontendRequestsAreStateful的注释:
protected $middlewareGroups = [ 'api' => [ \Fruitcake\Cors\HandleCors::class, \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];
2. 配置Sanctum信任域名
打开config/sanctum.php,在stateful数组里添加你的React域名:
'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) : '' )) . ',example.web.app'),
或者直接在.env文件里设置更方便:
SANCTUM_STATEFUL_DOMAINS=localhost:3000,example.web.app SESSION_DOMAIN=.your-laravel-domain.com # 注意前面的点,确保子域名也能共享Cookie(如果有需要)
3. 让Axios携带凭证
在React的Axios全局配置里开启withCredentials:
import axios from 'axios'; axios.defaults.withCredentials = true; // 或者针对单个请求单独设置 axios.get('/api/user', { withCredentials: true });
4. 按流程获取CSRF Cookie
跨域请求前必须先获取CSRF Cookie,再发起登录或其他认证请求:
// 先拿CSRF Cookie await axios.get('https://你的Laravel域名/sanctum/csrf-cookie'); // 再发登录请求 await axios.post('https://你的Laravel域名/api/login', { email: 'user@example.com', password: 'password' });
为什么之前会401?
- 没开
EnsureFrontendRequestsAreStateful,Sanctum不认跨域的会话,直接忽略认证Cookie - 前端域名不在信任列表里,Sanctum拒绝处理请求
- Axios没带凭证,Cookie根本传不到后端
总结
不用转JWT,Sanctum完全能搞定跨域认证。按上面的步骤改完配置,跨域请求就能正常通过认证了。
内容的提问来源于stack exchange,提问作者Gursahb Webcyst
相关产品推荐
相关产品推荐

