You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 08:28:07