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

Laravel Sanctum跨域认证失败:请求/user接口返回Unauthorized

Laravel Sanctum跨域授权失败排查与解决

问题场景

API部署地址:https://example.com,Vue.js应用部署地址:https://app.example.com,二者均为HTTPS域名。

已完成以下配置:

  1. .env配置:
SESSION_DOMAIN=.example.com
SANCTUM_STATEFUL_DOMAINS=https://app.example.com
  1. Axios配置:
import axios from 'axios'

const server = axios.create({
  baseURL: 'https://example.com'
})
server.defaults.withCredentials = true
server.defaults.withXSRFToken = true
  1. 曾在sanctum.php中设置guard为api:
'guard' => ['api']
  1. kernel.php的api中间件组配置:
'api' => [
        \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
  1. 全局$middleware组中添加:
\Illuminate\Session\Middleware\StartSession::class,

应用流程:点击登录按钮后,先请求/sanctum/csrf-cookie返回204并设置Cookie;接着登录请求也返回204,但请求受保护的/user接口(路由配置如下)时返回unauthorized:

Route::middleware('auth:sanctum')->group(function () {
    Route::get('/user', [UserController::class, 'index']);
});

Postman测试结果一致。


更新后的完整配置

config/sanctum.php

<?php

use Laravel\Sanctum\Sanctum;

return [

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        Sanctum::currentApplicationUrlWithPort()
    ))),

    'guard' => ['web'],

    'expiration' => null,

    'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),

    'middleware' => [
        'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class,
        'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
        'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
    ],

];

config/cors.php

<?php

return [
    
    'paths' => [
        'api/*',
        'login',
        'logout',
        'register',
        'sanctum/csrf-cookie'
    ],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,

];

config/session.php

<?php

use Illuminate\Support\Str;

return [

    'driver' => env('SESSION_DRIVER', 'file'),

    'lifetime' => env('SESSION_LIFETIME', 120),

    'expire_on_close' => false,

    'encrypt' => false,

    'files' => storage_path('framework/sessions'),

    'connection' => env('SESSION_CONNECTION'),

    'table' => 'sessions',

    'store' => env('SESSION_STORE'),

    'lottery' => [2, 100],

    'cookie' => env(
        'SESSION_COOKIE',
        Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
    ),

    'path' => '/',

    'domain' => env('SESSION_DOMAIN'),

    'secure' => env('SESSION_SECURE_COOKIE'),

    'http_only' => true,

    'same_site' => 'lax',

    'partitioned' => false,

];

config/auth.php

<?php

return [

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
    ],


    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_reset_tokens',
            'expire' => 60,
            'throttle' => 60,
        ],
    ],

    'password_timeout' => 10800,

];

.env

SESSION_DRIVER=cookie
SESSION_LIFETIME=120

SESSION_DOMAIN=.example.com
SANCTUM_STATEFUL_DOMAINS=https://app.example.com

问题排查与解决步骤

1. 修正Sanctum守卫与认证逻辑的匹配

从更新后的sanctum.php看,你已将guard改回['web'],但需确保登录逻辑使用web守卫处理:

  • 检查登录控制器,确认是通过Auth::attempt(...)(默认守卫为web)或Auth::guard('web')->attempt(...)完成登录,而非api守卫。误用api守卫会导致Session无法正确创建,进而让auth:sanctum无法识别登录状态。

2. 调整全局中间件与API中间件的冲突

你在全局$middleware中添加了StartSession,但web中间件组本身已包含该中间件,且api中间件组默认是无状态的,全局添加会导致Session初始化异常:

  • 移除全局$middleware中的\Illuminate\Session\Middleware\StartSession::class
  • 保留web中间件组内的StartSession(默认已包含)
  • api组中的EnsureFrontendRequestsAreStateful会自动为SANCTUM_STATEFUL_DOMAINS内的域名请求处理Session初始化

3. 确认Cookie的Secure属性

由于使用HTTPS域名,需在.env中强制开启Secure Cookie:

SESSION_SECURE_COOKIE=true

否则浏览器不会在HTTPS请求中携带Cookie。

4. 调整SameSite属性

当前session.php中same_site为lax,跨域POST请求(如登录)可能受限制,可临时改为none测试(需配合secure=true):

'same_site' => 'none',

测试通过后可根据业务场景决定是否保留该设置。

5. 清除缓存并重启服务

修改配置后必须清除Laravel缓存,否则修改不生效:

php artisan config:clear
php artisan cache:clear

若使用OPcache,需重启PHP服务或清除OPcache缓存。

6. Postman测试注意事项

在Postman中测试时需:

  • 在请求Headers中添加Origin: https://app.example.com
  • 开启Settings中的Send cookies选项
  • 按顺序请求/sanctum/csrf-cookie→登录接口→/user接口,确保Cookie被正确携带

内容的提问来源于stack exchange,提问作者sfarzoso

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 11:42:24