Sanctum SPA 身份验证:如何从其他设备注销?
Sanctum SPA Authentication: How to log out from other devices?
SPA 身份验证中是否包含此功能?通过阅读 Laravel Sanctum 上的文档,它看起来不像,但与此同时,这是一个常见的功能(如果用户重置密码或您只需要一个用户的登录实例)所以我认为它必须包括在内...
经过搜索,我发现了这个:
use Illuminate\Support\Facades\Auth;
Auth::logoutOtherDevices($currentPassword);
但您需要先在网络上取消对这个中间件的注释,然后才能使用它。
'web' => [
// ...
\Illuminate\Session\Middleware\AuthenticateSession::class,
// ...
],
然而,这仅适用于网络,不适用于 api。所以我再次用谷歌搜索如何使用 api 具有相同的功能,然后我找到了 this youttube video。这是这个人所做的:
- 创建自己的中间件(例如 AuthenticateSessionSPA.php)。
- 复制 AuthenticateSession 中的所有内容并将其粘贴到新的中间件中。更改命名空间和 class 名称。
- 创建值为 'sanctum' 的私有变量(例如 private $driver
= 'sanctum')
- 将所有 $this->auth->getDefaultDriver() 替换为 $this->driver。所以
该代码将改用 sanctum 驱动程序。
文件如下所示:
<?php
namespace App\Http\Middleware\Custom;
use Closure;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Auth\Factory as AuthFactory;
class AuthenticateSessionSPA
{
private $driver = 'sanctum';
/**
* The authentication factory implementation.
*
* @var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* Create a new middleware instance.
*
* @param \Illuminate\Contracts\Auth\Factory $auth
* @return void
*/
public function __construct(AuthFactory $auth)
{
$this->auth = $auth;
}
/**
* 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);
}
if ($this->guard()->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->driver)) {
$this->storePasswordHashInSession($request);
}
if ($request->session()->get('password_hash_'.$this->driver) !== $request->user()->getAuthPassword()) {
$this->logout($request);
}
return tap($next($request), function () use ($request) {
if (! is_null($this->guard()->user())) {
$this->storePasswordHashInSession($request);
}
});
}
/**
* Store the user's current password hash in the session.
*
* @param \Illuminate\Http\Request $request
* @return void
*/
protected function storePasswordHashInSession($request)
{
if (! $request->user()) {
return;
}
$request->session()->put([
'password_hash_'.$this->driver => $request->user()->getAuthPassword(),
]);
}
/**
* Log the user out of the application.
*
* @param \Illuminate\Http\Request $request
* @return void
*
* @throws \Illuminate\Auth\AuthenticationException
*/
protected function logout($request)
{
$this->guard()->logoutCurrentDevice();
$request->session()->flush();
throw new AuthenticationException('Unauthenticated.', [$this->driver]);
}
/**
* Get the guard instance that should be used by the middleware.
*
* @return \Illuminate\Contracts\Auth\Factory|\Illuminate\Contracts\Auth\Guard
*/
protected function guard()
{
return $this->auth;
}
}
这非常有效,我现在可以在 api.
中使用 Auth::logoutOtherDevices($currentPassword)
所以我的问题是这是否安全?我只是个jr开发(6 个月),我对这个解决方案不太有信心,因为我是从网上的某个人那里找到的,而不是从文档中找到的。我想知道也许 laravel 开发人员没有实施它是因为他们出于安全原因?
你对这个方法有什么看法?如果您不同意这一点,您将如何在具有 SPA 前端和 Laravel api 的项目中实现从其他设备注销?
Laravel Sanctum SPA 身份验证中似乎没有包含此内容。所以我只是做了我在 the youtube video
上找到的原始答案
SPA 身份验证中是否包含此功能?通过阅读 Laravel Sanctum 上的文档,它看起来不像,但与此同时,这是一个常见的功能(如果用户重置密码或您只需要一个用户的登录实例)所以我认为它必须包括在内...
经过搜索,我发现了这个:
use Illuminate\Support\Facades\Auth;
Auth::logoutOtherDevices($currentPassword);
但您需要先在网络上取消对这个中间件的注释,然后才能使用它。
'web' => [
// ...
\Illuminate\Session\Middleware\AuthenticateSession::class,
// ...
],
然而,这仅适用于网络,不适用于 api。所以我再次用谷歌搜索如何使用 api 具有相同的功能,然后我找到了 this youttube video。这是这个人所做的:
- 创建自己的中间件(例如 AuthenticateSessionSPA.php)。
- 复制 AuthenticateSession 中的所有内容并将其粘贴到新的中间件中。更改命名空间和 class 名称。
- 创建值为 'sanctum' 的私有变量(例如 private $driver = 'sanctum')
- 将所有 $this->auth->getDefaultDriver() 替换为 $this->driver。所以 该代码将改用 sanctum 驱动程序。
文件如下所示:
<?php
namespace App\Http\Middleware\Custom;
use Closure;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Auth\Factory as AuthFactory;
class AuthenticateSessionSPA
{
private $driver = 'sanctum';
/**
* The authentication factory implementation.
*
* @var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* Create a new middleware instance.
*
* @param \Illuminate\Contracts\Auth\Factory $auth
* @return void
*/
public function __construct(AuthFactory $auth)
{
$this->auth = $auth;
}
/**
* 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);
}
if ($this->guard()->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->driver)) {
$this->storePasswordHashInSession($request);
}
if ($request->session()->get('password_hash_'.$this->driver) !== $request->user()->getAuthPassword()) {
$this->logout($request);
}
return tap($next($request), function () use ($request) {
if (! is_null($this->guard()->user())) {
$this->storePasswordHashInSession($request);
}
});
}
/**
* Store the user's current password hash in the session.
*
* @param \Illuminate\Http\Request $request
* @return void
*/
protected function storePasswordHashInSession($request)
{
if (! $request->user()) {
return;
}
$request->session()->put([
'password_hash_'.$this->driver => $request->user()->getAuthPassword(),
]);
}
/**
* Log the user out of the application.
*
* @param \Illuminate\Http\Request $request
* @return void
*
* @throws \Illuminate\Auth\AuthenticationException
*/
protected function logout($request)
{
$this->guard()->logoutCurrentDevice();
$request->session()->flush();
throw new AuthenticationException('Unauthenticated.', [$this->driver]);
}
/**
* Get the guard instance that should be used by the middleware.
*
* @return \Illuminate\Contracts\Auth\Factory|\Illuminate\Contracts\Auth\Guard
*/
protected function guard()
{
return $this->auth;
}
}
这非常有效,我现在可以在 api.
中使用 Auth::logoutOtherDevices($currentPassword)所以我的问题是这是否安全?我只是个jr开发(6 个月),我对这个解决方案不太有信心,因为我是从网上的某个人那里找到的,而不是从文档中找到的。我想知道也许 laravel 开发人员没有实施它是因为他们出于安全原因?
你对这个方法有什么看法?如果您不同意这一点,您将如何在具有 SPA 前端和 Laravel api 的项目中实现从其他设备注销?
Laravel Sanctum SPA 身份验证中似乎没有包含此内容。所以我只是做了我在 the youtube video
上找到的原始答案