如何使用check-sso及指定PHP库无跳转检查Keycloak用户登录状态
无跳转检查Keycloak登录状态(基于Check SSO)
结合你使用的两个OAuth2库,可通过以下步骤实现无跳转的登录状态检查:
1. 后端生成静默授权URL
在Symfony控制器中新增方法,生成带prompt=none参数的Keycloak授权URL——这个参数会告知Keycloak无需弹出登录界面,直接返回登录状态:
/** * @Route("/keycloak/check-sso", name="keycloak_check_sso") */ public function checkSsoAction(ClientRegistry $clientRegistry) { /** @var \Stevenmaguire\OAuth2\Client\Provider\Keycloak $provider */ $provider = $clientRegistry->getClient('keycloak')->getOAuth2Provider(); // 构建静默授权请求URL $authUrl = $provider->getAuthorizationUrl([ 'scope' => ['openid', 'profile', 'email', 'roles'], 'prompt' => 'none', // 核心参数:无交互,不跳转登录页 'response_mode' => 'fragment', // 让返回结果放在URL片段中,方便前端解析 ]); return $this->json(['auth_url' => $authUrl]); }
2. 前端通过iframe发起静默请求
前端用iframe加载上述URL,监听结果判断登录状态(避免页面跳转):
function checkKeycloakAuthStatus() { const iframe = document.createElement('iframe'); iframe.style.display = 'none'; // 先从后端获取静默授权URL fetch('/keycloak/check-sso') .then(res => res.json()) .then(data => { iframe.src = data.auth_url; document.body.appendChild(iframe); iframe.onload = function() { try { const hash = iframe.contentWindow.location.hash; const params = new URLSearchParams(hash.slice(1)); if (params.has('id_token')) { // 用户已登录,将ID Token发送到后端验证有效性 fetch('/keycloak/validate-token', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({id_token: params.get('id_token')}) }) .then(res => res.json()) .then(result => { if (result.valid) { console.log('用户已登录Keycloak'); // 这里可以更新页面状态,比如显示用户信息 } else { console.log('Token无效或已过期'); } }); } else if (params.get('error') === 'login_required') { console.log('用户未登录Keycloak'); } } catch (e) { console.error('跨域访问受限,请检查Keycloak的Web Origins配置'); } document.body.removeChild(iframe); }; }); } // 页面加载时执行检查 checkKeycloakAuthStatus();
3. 后端验证ID Token(可选但建议)
新增后端接口验证前端传来的ID Token,确保其合法有效:
/** * @Route("/keycloak/validate-token", name="keycloak_validate_token", methods={"POST"}) */ public function validateTokenAction(Request $request, ClientRegistry $clientRegistry) { $requestData = json_decode($request->getContent(), true); $idToken = $requestData['id_token'] ?? null; if (!$idToken) { return $this->json(['valid' => false], 400); } /** @var \Stevenmaguire\OAuth2\Client\Provider\Keycloak $provider */ $provider = $clientRegistry->getClient('keycloak')->getOAuth2Provider(); try { $token = $provider->parseIdToken($idToken); // 额外检查token是否过期 if ($token->isExpired()) { return $this->json(['valid' => false]); } // 返回验证结果及用户信息 return $this->json([ 'valid' => true, 'user_info' => $token->getClaims() ]); } catch (\Exception $e) { return $this->json(['valid' => false, 'error' => $e->getMessage()]); } }
4. Keycloak客户端配置检查
确保Keycloak客户端的以下配置正确:
- Valid Redirect URIs:包含你的应用域名(例如
http://your-app-domain/*) - 启用Implicit Flow或Authorization Code Flow with PKCE(PKCE更安全,需前端额外处理代码挑战)
- Web Origins:添加你的应用域名,允许跨域访问iframe内容
内容的提问来源于stack exchange,提问作者Dariusz Rup
相关产品推荐
相关产品推荐

