React请求Laravel Sanctum保护的API返回401未授权如何解决
问题根因
- 请求时序错误:React端两个请求并行触发,
/token请求还没完成、Cookie还未种下时就已经发起了受保护接口的请求,自然带不上令牌 - Sanctum默认不会读取Cookie中的令牌:Sanctum默认从
Authorization请求头的Bearer字段或请求参数取令牌,你把令牌存在名为Authorization的Cookie里,框架不会主动解析 - 跨域配置缺失:前后端分离场景下未正确配置CORS规则,导致浏览器拒收Laravel返回的Set-Cookie头
- 代码语法错误:受保护接口路径拼写错误(
taks应为tasks)、异步处理逻辑错误、this指向错误
修复方案
1. Laravel端修改
自定义Sanctum令牌解析逻辑
在app/Providers/AppServiceProvider.php的boot方法中添加代码,让Sanctum从Cookie中读取令牌:
use Laravel\Sanctum\Sanctum; use Illuminate\Http\Request; public function boot() { Sanctum::getAccessTokenFromRequestUsing(function (Request $request) { return $request->cookie('Authorization'); }); }
修正跨域配置
打开config/cors.php修改以下配置:
return [ 'paths' => ['api/*', 'token'], // 覆盖你用到的所有接口路径 'allowed_origins' => ['http://localhost:3000'], // 改成你React服务的实际地址,不能用* 'supports_credentials' => true, // 必须设为true允许携带凭证 // 其余配置保持默认即可 ];
完善Cookie参数
修改生成令牌的方法,明确Cookie的作用域和属性,避免跨域场景下被浏览器拒收:
public function getToken(){ $user = User::first(); $token = $user->createToken('Authorization', ['server:update'])->plainTextToken; // 本地开发时域名填localhost,生产环境换成你的实际域名,https环境下倒数第三个参数改为true Cookie::queue("Authorization", $token, 60*24, '/', 'localhost', false, true, false, 'lax'); return $token; }
2. React端修改
修正异步请求时序,全局配置axios凭证携带,修复语法错误:
// 全局配置axios,避免每个请求重复加参数 axios.defaults.withCredentials = true; axios.defaults.baseURL = 'http://localhost:8000'; // 等token请求完成后再发起业务请求 axios.get('/token') .then(async () => { // 注意路径拼写修正为tasks const taskRes = await axios.get('/api/tasks/all-tasks'); const json = taskRes.data; console.log('Json', json); // 此处处理业务数据逻辑 }) .catch(err => { console.error('请求异常', err); });
验证步骤
- 打开浏览器F12控制台,切换到「应用/存储」标签,请求
/token后查看是否存在AuthorizationCookie - 查看受保护接口的请求头,确认
Cookie字段中已经携带了Authorization的值,且Origin和Laravel CORS配置的地址一致 - 查看Laravel返回的响应头,确认存在
Access-Control-Allow-Credentials: true
内容的提问来源于stack exchange,提问作者Krystian432345
相关产品推荐
相关产品推荐

