用户在前端登录以后,获取 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