Laravel 11 Sanctum SPA调用Auth::logoutOtherDevices登出其他设备失败
问题:Sanctum SPA会话认证下调用
Auth::logoutOtherDevices()报错 我们在实现基于会话的Sanctum SPA认证(非API令牌)时,用户修改密码后尝试调用Auth::logoutOtherDevices($password);登出其他设备失败,报错信息如下:
error: Method Illuminate\Auth\RequestGuard::logoutOtherDevices does not exist. in /fooapp/vendor/laravel/framework/src/Illuminate/Macroable/Traits/Macroable.php line 115
当前配置
- web.php路由:
Route::middleware(['auth:sanctum'])->group(function () { Route::put('auth/passwordUpdate', [AuthController::class, 'passwordUpdate']); });
- AuthController.php的passwordUpdate方法:
<?php namespace App\Http\Controllers; use App\Models\User; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Auth; class AuthController extends BaseController { public function passwordUpdate(Request $request) { $user = User::where('username', $this->user()->username)->first(); if (! Hash::check($request->get('password'), $user->password)) { return response()->error('Incorrect password provided.'); } try { $user->password = Hash::make($request->get('passwordNew')); $user->save(); // Logout user from other devices if they have any active sessions there // *** Not working with sanctum at the moment and errors out as seen above Auth::logoutOtherDevices($request->get('passwordNew')); } catch (\Exception $e) { return $this->dbRollbackLogAndReturnError($e, $customErrorMessage); } return response()->success('You have updated your password successfully.'); } }
- sanctum.php配置:
<?php use Laravel\Sanctum\Sanctum; return [ ... 'guard' => ['web'], ... 'middleware' => [ 'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class, 'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class, 'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class, ], ];
- app.php配置:
<?php use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Middleware; use Illuminate\Foundation\Configuration\Exceptions; return Application::configure(basePath: dirname(__DIR__)) ->withProviders([ ... ]) ->withRouting( web: __DIR__.'/../routes/web.php', api: __DIR__.'/../routes/api.php', commands: __DIR__.'/../routes/console.php', channels: __DIR__.'/../routes/channels.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { $middleware->statefulApi(); // sanctum }) ->withExceptions(function (Exceptions $exceptions) { ... })->create();
解决方案(Laravel 11标准方案)
问题原因
Auth::logoutOtherDevices()是Web守卫(SessionGuard)提供的方法,但当前路由使用auth:sanctum守卫时,默认的Auth门面绑定的是Sanctum的RequestGuard,该守卫没有这个方法。不过你的sanctum配置已指定依赖web守卫,只需明确调用web守卫的实例即可。
具体步骤
- 明确指定Web守卫调用方法
将控制器中的Auth::logoutOtherDevices($request->get('passwordNew'));修改为:
Auth::guard('web')->logoutOtherDevices($request->get('passwordNew'));
确认中间件生效
你的sanctum配置已包含AuthenticateSession中间件,该中间件是logoutOtherDevices功能的依赖,确保路由通过auth:sanctum中间件时能自动应用这些配置的中间件(当前配置已满足)。优化用户查询(可选)
当前代码中通过User::where('username', $this->user()->username)->first();查询用户是冗余操作,直接使用$this->user()即可获取当前认证的用户实例:
$user = $this->user();
修改后的控制器代码示例
<?php namespace App\Http\Controllers; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Auth; class AuthController extends BaseController { public function passwordUpdate(Request $request) { $user = $this->user(); if (! Hash::check($request->get('password'), $user->password)) { return response()->error('提供的密码不正确。'); } try { $user->password = Hash::make($request->get('passwordNew')); $user->save(); // 使用web守卫登出其他设备 Auth::guard('web')->logoutOtherDevices($request->get('passwordNew')); } catch (\Exception $e) { return $this->dbRollbackLogAndReturnError($e, '密码更新失败'); } return response()->success('密码已成功更新。'); } }
内容的提问来源于stack exchange,提问作者Wonka
相关产品推荐
相关产品推荐

