php - “logoutOtherDevices”不适用于 Laravel Sanctum
问题描述
更改密码后,我想Auth::logoutOtherDevices($currentPassword)
在 laravel 8 中使用从其他设备注销用户。根据文档,我取消了该行的注释\Illuminate\Session\Middleware\AuthenticateSession::class,
。但不幸的是,它不起作用。它说Method Illuminate\Auth\RequestGuard::viaRemember does not exist.
任何人都可以帮我解决一下如何在Auth::logoutOtherDevices($currentPassword)
任何手动方法的帮助下从其他设备功能中添加注销?
这是我的代码:
$rules = [
'currentpass' => 'required',
'newpass' => 'required|min:6',
'confnewpass' => 'required|same:newpass|min:6'
];
$messages = [
'currentpass.required' => 'Please enter your current password.',
'newpass.required' => 'Please provide a new password.',
'newpass.min' => 'Password must contain minimum 6 characters.',
'confnewpass.required' => 'Please provide your new password again to confirm.',
'confnewpass.same' => 'Both new passwords must be same.',
'confnewpass.min' => 'Password must contain minimum 6 characters.'
];
$this->validate($request, $rules, $messages);
$currentPass = $request->input('currentpass');
$newPass = $request->input('newpass');
try {
$user = User::findOrFail(Auth::id());
} catch (ModelNotFoundException $ex) {
$response['error'] = true;
$response['errors']['notFound'] = ['User Not Found.'];
return response()
->json($response, 400, [], JSON_PRETTY_PRINT);
}
if (!Hash::check($currentPass, $user->password)) {
return Redirect::back()
->withErrors(['Current Password', 'Please provide your current password properly.']);
}
$isChar = preg_match('/[a-zA-Z]+/', $newPass);
$isNum = preg_match('/\d+/', $newPass);
if (!($isChar && $isNum)) {
$response['error'] = 'Password must contain minimum 6 characters with at-least one letter and one number.';
return response()
->json($response, 200, [], JSON_PRETTY_PRINT);
}
/** hash password */
$hashpass = Hash::make($newPass);
$user->password = $hashpass;
try {
$user->save();
} catch (QueryException $ex) {
return Redirect::back()
->withErrors(['query', $ex->getMessage()]);
}
Auth::logoutOtherDevices($currentPass);
return Redirect::back()
->with('success', 'Your password has been successfully updated.');
解决方案
这是因为 Laravel Sanctum 使用了自己的中间件,即Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful
. 虽然Auth::logoutOtherDevices($currentPassword)
需要\Illuminate\Session\Middleware\AuthenticateSession
工作。
要解决此问题,您可以扩展\Illuminate\Session\Middleware\AuthenticateSession
到使用Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful
. 以下是步骤:
AuthenticateApiSession.php
在app/Http/Middleware
(或您喜欢的任何其他文件夹)中创建一个新文件。AuthenticateApiSession.php
应该是这样的:<?php namespace App\Http\Middleware; use Closure; use Illuminate\Session\Middleware\AuthenticateSession; class AuthenticateApiSession extends AuthenticateSession { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if (! $request->hasSession() || ! $request->user()) { return $next($request); } // Remove or comment this code block, or you'll get error. /*if ($this->auth->viaRemember()) { $passwordHash = explode('|', $request->cookies->get($this->auth->getRecallerName()))[2] ?? null; if (! $passwordHash || $passwordHash != $request->user()->getAuthPassword()) { $this->logout($request); } }*/ if (! $request->session()->has('password_hash')) { $this->storePasswordHashInSession($request); } if ($request->session()->get('password_hash') !== $request->user()->getAuthPassword()) { $this->logout($request); } return tap($next($request), function () use ($request) { $this->storePasswordHashInSession($request); }); } }
将新创建的
App\http\Middleware\AuthenticateApiSession
类添加api
到app/Http/Kernel.php
. 请注意,它必须在 之后插入EnsureFrontendRequestsAreStateful
。'api' => [ EnsureFrontendRequestsAreStateful::class, \App\Http\Middleware\AuthenticateApiSession::class, 'throttle:240,1', 'auth:airlock', 'branch.default', 'bindings', ],
就是这样,现在从其他设备对受保护的 API 端点的每个 ajax 请求都应该在调用401
后返回响应。Auth::logoutOtherDevices($currentPassword)
您应该设置您的 SPA(您正在使用 sanctum,所以我假设您正在构建一个 SPA)以处理 ajax 请求中的无效会话。401
遇到ajax 响应时,可能会使用 javascript 将用户重定向到登录页面。
推荐阅读
- linux - 如何在不使用 sudo 且不在根目录下运行 man ?
- integration - 迄今为止,人工制品将人工制品标记为“集成”不起作用
- ruby - 这是很好的解决方案吗?
- php - PHP 出现错误:在设置标头('charset=utf-8')中找不到文件;
- python - 井字游戏的 If 语句问题
- airflow - 如何在 Airflow 中使用 SimpleHttpOperator
- android - 可观察的 RxJava 测试“重复”在测试中创建无限循环
- localhost - 如何使用我的 IP 而不是 localhost 访问我的网站?
- c - 由于往返延迟,如何及时纠正 ntp 客户端应用程序的错误
- java - 终端中的 Visual Studio Code Java 路径