为啥我的 CSRF 令牌与 Laravel 和 Sanctum 不匹配?

Posted

技术标签:

【中文标题】为啥我的 CSRF 令牌与 Laravel 和 Sanctum 不匹配?【英文标题】:Why am I getting a CSRF token mismatch with Laravel and Sanctum?为什么我的 CSRF 令牌与 Laravel 和 Sanctum 不匹配? 【发布时间】:2022-01-11 19:34:12 【问题描述】:

我有一个 Laravel 后端和反应前端,我使用 sanctum 进行 SPA 身份验证,并使用 Axios 来提出我的请求。我在 http://localhost:8000 上使用本地主机,在 http://localhost:3000 上使用前端。

这是我的前端代码:

const apiClient = axios.create(
    baseURL: `http://localhost:8000`,
    withCredentials: true,
);    

let config = 
    headers: 
        'Content-Type': 'application/json'
    ,


export async function login(credentials: LoginCredentials) 

    return apiClient.get('sanctum/csrf-cookie', config).then(response => 
        apiClient.post('/api/v1/login', JSON.stringify(credentials));
    );

我的 api 中间件类是这样的

'api' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            'throttle:api',
        ],

这些是我的圣所配置;

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,localhost:3000/api/v1/login,127.0.0.1,127.0.0.1:8000,::1',
        env('APP_URL') ? ','.parse_url(env('APP_URL'), php_URL_HOST) : ''
    ))),

SESSION_DOMAIN=http://localhost:3000

最后是我的 cors 中间件

    'paths' => ['api/*', 'sanctum/csrf-cookie'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,

我很确定我错过了一些小事。任何帮助都将不胜感激

【问题讨论】:

能否在标题中添加Acceptapplication/json 您不需要为localhost:3000 设置SESSION_DOMAIN,因为它已作为默认值包含在内。此外,您应该只需要添加域,即不包括 http:// 位。您从login 请求中得到什么响应/状态(网络选项卡)? @Faesal 将接受与应用程序 json 结合使用不会改变任何内容。 @Rwd 我得到的响应状态是令牌不匹配异常 从我的 api 中间件中删除 \App\Http\Middleware\VerifyCsrfToken::class 【参考方案1】:

因为您使用的是 post 方法。您有两种方法可以解决此问题:

1-使用get方法

2- 走这条路

app/http/middleware/VerifyCsrfToken.php

在里面设置你的路径

protected $except = []

用于异常 csrf 令牌。

【讨论】:

我正在发出登录请求,所以它将是一个发布请求。 好的。我知道。您只需使用上述说明进行修复。相信我【参考方案2】:

你遇到这个问题的原因是你需要点击 csrf-cookie 在您可以登录或注册之前(您在发送帖子但未登录时会遇到同样的问题。)

await this.$axios( url: "/v1/sanctum/csrf-cookie" );

文档中也提到了这一点 https://laravel.com/docs/8.x/sanctum#csrf-protection

你可以使用php artisan route:list找到csrf-cookie路由

你也可以在 config/santrum 中设置你自己的 csrf-cookie 路由 'prefix' => 'api/v1/sanctum'

【讨论】:

以上是关于为啥我的 CSRF 令牌与 Laravel 和 Sanctum 不匹配?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Laravel 中禁用 CSRF 令牌以及为啥我们必须禁用它?

为啥 Laravel 4 CSRF 令牌不起作用?

为啥我的 CSRF 令牌在使用 Form::open() 时是空的?

如何在 vuejs 组件中使用 laravel csrf 令牌

角度中的 CSRF 令牌与 Laravel 5 不同

laravel 7 csrf 令牌不匹配