You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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认证,你的问题出在几个关键配置缺失上:

  1. 注释掉了EnsureFrontendRequestsAreStateful中间件——这是Sanctum处理跨域有状态请求的核心,没它Cookie根本没法正常传递和验证
  2. 没把前端域名加入Sanctum的信任列表
  3. 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 });

跨域请求前必须先获取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 15:32:31