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

如何使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 14:30:35