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

Spring集成Keycloak:无需显式REST实现Access Token Introspection

解决方案:通过Keycloak工具实现令牌Introspection(无需显式POST请求)

针对Keycloak 22.0.1对接Spring API的场景,官方org.keycloak.admin.client确实没有直接暴露令牌Introspection的API,但可以通过两种间接方式实现需求,避免手动编写POST请求逻辑:

方式一:复用Admin Client的底层HTTP客户端调用Introspection端点

Admin Client内部封装了JAX-RS客户端,可直接复用它来调用Keycloak标准的Introspection端点,无需额外创建HTTP客户端实例。

代码示例

import org.keycloak.admin.client.Keycloak;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.Response;
import java.util.Map;

// 假设已初始化好Keycloak adminClient实例
public Map<String, Object> introspectToken(String accessToken) {
    String serverUrl = adminClient.getAuthRealm().getServerUrl();
    String targetRealm = "你的目标Realm(如master)";
    String introspectEndpoint = String.format("%s/realms/%s/protocol/openid-connect/token/introspect", serverUrl, targetRealm);

    // 构造Introspection请求表单
    Form form = new Form();
    form.param("token", accessToken);
    form.param("client_id", adminClient.getConfig().getClientId());
    form.param("client_secret", adminClient.getConfig().getClientSecret());

    try (Response response = adminClient.getRealmResource(targetRealm).getRestClient()
            .target(introspectEndpoint)
            .request()
            .post(javax.ws.rs.client.Entity.form(form))) {

        if (response.getStatus() == 200) {
            return response.readEntity(Map.class);
        } else {
            throw new RuntimeException("令牌校验失败,状态码:" + response.getStatus());
        }
    }
}

说明:

  • 复用Admin Client已配置的客户端凭证,无需重复定义
  • 返回的Map包含active(令牌是否有效)、exp(过期时间)、session_state(会话状态)等字段,可直接用于判断令牌有效性和会话活跃度

方式二:使用Keycloak授权客户端库(keycloak-authz-client)

如果允许引入额外依赖,官方的keycloak-authz-client库封装了完整的Introspection逻辑,代码更简洁。

步骤1:添加Maven依赖

<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-authz-client</artifactId>
    <version>22.0.1</version>
</dependency>

步骤2:配置并调用

import org.keycloak.authorization.client.AuthzClient;
import org.keycloak.representations.idm.authorization.IntrospectionResponse;

// 复用Admin Client的配置初始化AuthzClient
AuthzClient authzClient = AuthzClient.create(Map.of(
        "server-url", adminClient.getConfig().getServerUrl(),
        "realm", "你的目标Realm",
        "client-id", adminClient.getConfig().getClientId(),
        "client-secret", adminClient.getConfig().getClientSecret(),
        "grant-type", "client_credentials"
));

public boolean isTokenActiveAndSessionValid(String accessToken) {
    IntrospectionResponse response = authzClient.protection().introspectToken(accessToken);
    // 同时判断令牌是否有效、会话是否存在
    return response.getActive() && response.getSessionState() != null;
}

说明:

  • 官方维护的授权客户端库,专门处理权限校验相关操作,稳定性更高
  • IntrospectionResponse封装了所有校验结果,可直接提取所需字段

注意事项

  • 权限要求:用于调用Introspection端点的客户端,只需配置client_secret即可,无需额外的Admin权限
  • 性能优化:每次请求都调用Introspection会增加Keycloak负载,建议结合本地缓存(如Redis),对未过期且已验证的令牌进行缓存,减少重复调用
  • 混合校验:对于JWT格式的Access Token,可先本地验证签名和过期时间,再定期调用Introspection检查会话活跃度,平衡安全性与性能

内容的提问来源于stack exchange,提问作者Alejandro Silva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 01:32:22