php - Laravel Passport在前后端分离项目中的使用问题
本文介绍了php - Laravel Passport在前后端分离项目中的使用问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
问 题
描述:
用户在前端登录以后,获取access_token
,保存至localStorage
,用户注销则销毁localStorage
中的access_token
。如果过期时间8小时的话,在access_token
未过期的时间内,用户多次注销和登录,依然会产生多个access_token
,且都是有效的!
问题:
如何合理的设置过期时间 ?
如何保证用户的同一
Client_id
的access_token
只有一个是有效的(未过期的)?如何清理过期或被撤销的
access_token
?
解决方案
通过事件监听来清理token的方法:
将事件注册到 EventServiceProvider
中,代码如下:
protected $listen = [
'App\Events\SomeEvent' => [
'App\Listeners\EventListener',
],
'Laravel\Passport\Events\AccessTokenCreated' => [
'App\Listeners\Auth\RevokeOldTokens',
],
'Laravel\Passport\Events\RefreshTokenCreated' => [
'App\Listeners\Auth\PruneOldTokens',
],
];
然后创建两个事件的 Listener
:
RevokeOldTokens:
/**
* Handle the event.
*
* @param AccessTokenCreated $event
* @return void
*/
public function handle(AccessTokenCreated $event)
{
Token::where('id', '!=', $event->tokenId)
->where('user_id', $event->userId)
->where('client_id', $event->clientId)
->where('expires_at', '<', Carbon::now())
->orWhere('revoked', true)
->delete();
}
PruneOldTokens:
/**
* Handle the event.
*
* @param RefreshTokenCreated $event
* @return void
*/
public function handle(RefreshTokenCreated $event)
{
DB::table('oauth_refresh_tokens')
->where('access_token_id', '!=', $event->accessTokenId)
->where('revoked', true)->delete();
}
解决注销之后再登录的密码验证问题
因为前端登录后会将
refresh_tokens
和access_token
保存到localStorage中,当用户注销登录以后,则将vuex state 中的状态销毁,仅保留refresh_tokens
。当用户下次登录时前端会检测refresh_tokens
,如果存在则发起refresh_tokens
请求,无需验证用户名密码。处于安全考虑即使存在refresh_tokens
也要验证用户名密码是否正确,于是就动手改了LoginController
!
public function login(Request $request)
{
$credentials = $this->credentials($request);
if ($this->guard('api')->attempt($credentials, $request->has('remember'))) {
return $this->sendLoginResponse($request);
}
return \Response::json([
'status' => "error",
'message' => "用户名或密码有误"
], 401);
}
protected function sendLoginResponse(Request $request)
{
$this->clearLoginAttempts($request);
return $this->authenticated($request);
}
protected function authenticated(Request $request)
{
return $this->authenticateClient($request);
}
protected function authenticateClient(Request $request)
{
$data = $request->all();
if ($request->refresh_token) {
$request->request->add([
'grant_type' => $data['grant_type'],
'client_id' => $data['client_id'],
'client_secret' => $data['client_secret'],
'refresh_token' => $data['refresh_token'],
'scope' => ''
]);
} else {
$request->request->add([
'grant_type' => $data['grant_type'],
'client_id' => $data['client_id'],
'client_secret' => $data['client_secret'],
'username' => $data['staffid'],
'password' => $data['password'],
'scope' => ''
]);
}
$proxy = Request::create(
'oauth/token',
'POST'
);
$response = \Route::dispatch($proxy);
$token = json_decode($response->getContent());
$token->user = $request->user();
return response()->json($token);
}
/**
* Get the login username to be used by the controller.
*
* @return string
*/
public function username()
{
return 'staffid';
}
这篇关于php - Laravel Passport在前后端分离项目中的使用问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文