如何通过 Sanctum SPA 从 Laravel 注销

How to log out from Laravel via Sanctum SPA

我有一个 Vue.js SPA (app.example.com) 与后端 Laravel 应用程序 (accounts.example.com) 通信。身份验证由 Laravel 应用程序处理 - 如果未经身份验证的用户访问 SPA,他们将被重定向到 Laravel 应用程序以登录,然后重定向回 SPA。

Laravel 应用程序有一个 LoginController 使用 Laravel 的内置 Illuminate\Foundation\Auth\AuthenticatesUsers 特性。登录完美。

我遇到的问题是注销 - 我在 SPA 中有一个“注销”按钮需要注销 Laravel 会话。

为了防止通过 CSRF 拒绝服务,Laravel 的默认注销路由(在 routes/web.php -- Route::post('logout', [LoginController::class, 'logout']) 中)仅接受 POST 请求,而不是 GET 个请求。此外,注销 POST 必须在 _token 字段中包含 CSRF 令牌。

默认情况下,我无法访问 SPA 中的原始 CSRF 令牌,只能访问 /sanctum/csrf-cookie 提供的加密版本,所以我不能只创建一个表单并拥有 [=44= 】 提交吧。出于同样的原因,我也无法使用 axios 进行注销。

我尝试像这样添加另一个路由(在 routes/api.php 中),因此将调用相同的注销函数,但应用 api 中间件组而不是 web 中间件组:

Route::post('/logout', [\App\Http\Controllers\Auth\LoginController::class, 'logout']);

调用此端点时出现错误:

Method Illuminate\Auth\RequestGuard::logout does not exist.

如何在不禁用 CSRF 保护或启用 GET 请求注销的情况下使此注销工作?

我在 Laravel Sanctum 存储库中找到了 this discussion

基于此,我在 routes/api.php 中更改了路线,如下所示:

Route::post('/logout', [\App\Http\Controllers\Auth\LoginController::class, 'logout'])
    ->middleware('auth:web');

这告诉注销 API 调用使用 SessionGuard 而不是 RequestGuard,并解决了问题。