Laravel 11 + Passport 12 SSO服务端登出后自动登录的问题排查及解决方案咨询
Laravel 11 + Passport 12 SSO服务端登出后自动登录的问题排查及解决方案咨询
我最近基于Laravel 11和Laravel Passport 12搭建了一个SSO认证服务,用来给外部电商网站做用户登录授权。登录流程一切正常:用户在电商站点点击登录按钮,会跳转到SSO服务的登录页,验证通过后自动回到电商站点。但登出环节遇到了棘手的问题:
当用户在电商站点发起登出时,我已经完成了两个操作:一是在电商端销毁了用户的本地会话,二是调用SSO服务的接口撤销了此次登录对应的access_token和refresh_token。但奇怪的是,用户紧接着点击登录按钮,SSO服务会自动完成登录流程,完全不需要用户输入账号密码。
我的排查思路
我初步判断问题出在SSO服务端的Laravel Session Cookie上,做了以下测试验证:
- 如果将SSO服务的session cookie设置为「浏览器关闭即过期」,关闭再重新打开浏览器后,SSO会正常要求用户输入登录凭证;
- 但如果保持默认的session cookie过期设置,哪怕关闭再打开浏览器,SSO依然会自动登录用户。
这说明:当电商站点跳转到SSO登录页时,SSO服务端已经为用户创建了会话,而这个会话在用户从电商站点登出时没有被正确销毁,导致SSO服务一直认为用户处于登录状态。
当前的登出实现
我在SSO服务端写了一个sso_logout方法来处理跨站登出逻辑,代码如下:
public function sso_logout(Request $request) { // 从会话中获取redirect_uri,不存在则用默认地址 $redirectUri = session('redirect_uri', "https://default.com"); // 撤销access_token和refresh_token $user = $request->user('api'); if ($user) { $token = $user->token(); $tokenRepository = app(TokenRepository::class); $refreshTokenRepository = app(RefreshTokenRepository::class); // 撤销access token $tokenRepository->revokeAccessToken($token->id); // 撤销该access token关联的所有refresh token $refreshTokenRepository->revokeRefreshTokensByAccessTokenId($token->id); } // 登出用户并销毁会话 $this->guard()->logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); if ($response = $this->loggedOut($request)) { return $response; } // 处理跳转会电商站点的逻辑(只保留域名部分) if ($redirectUri != "https://default.com") { $redirectUri = parse_url($redirectUri, PHP_URL_SCHEME) . '://' . parse_url($redirectUri, PHP_URL_HOST); } return $request->wantsJson() ? new JsonResponse([], 204) : redirect($redirectUri); }
这个方法通过web路由对外暴露:
Route::get('/sso/logout', [LoginController::class, 'sso_logout'])->name('sso.logout');
目前token撤销的逻辑是有效的——数据库里对应的token确实被标记为已撤销,但会话销毁的操作完全没起作用。
我尝试过的修复方案
为了彻底销毁SSO服务端的用户会话,我还额外加了这些操作,但都没有效果:
- 显式指定web guard执行登出:
Auth::guard('web')->logout(); - 强制清空所有会话数据:
Session::flush(); - 手动删除session相关的Cookie:
Cookie::queue(Cookie::forget('laravel_token')); Cookie::queue(Cookie::forget('pegasus_api_session'));
我的疑问
现在我有点迷茫,是不是我的SSO登录/登出流程设计本身就有问题?或者我对SSO的核心逻辑理解有误?有没有正确的处理方式,能让用户在电商站点登出后,下次跳转到SSO登录页时必须重新输入账号密码?
内容来源于stack exchange
相关产品推荐
相关产品推荐

