You need to enable JavaScript to run this app. 如何在SpringBoot项目中从Keycloak获取Access Token?现有实现返回null求方案
优惠活动
大模型
产品
解决方案
定价
更多

如何在SpringBoot项目中从Keycloak获取Access Token?现有实现返回null求方案

你原写法中KeycloakAuthenticationToken为null的核心原因是该方式仅适用于请求已经通过Keycloak Spring Security适配器认证的场景,如果请求路径配置了免认证、适配器配置错误、版本不匹配都会导致拿不到Principal。

场景1:获取当前登录用户的AccessToken(已完成SSO认证)

方案1:Controller参数直接注入

Spring Security会自动将当前认证信息注入到参数中,无需手动从Request中解析:

@GetMapping("/token")
public String getToken(KeycloakAuthenticationToken token) throws IOException {
    RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) token.getAccount().getKeycloakSecurityContext();
    // 原有序列化逻辑不变
    return JsonSerialization.writeValueAsPrettyString(session.getToken());
}

注意需要确保该接口路径在Spring Security配置中为需要认证的路径,没有配置permitAll。

方案2:全局静态获取

适合在Service、工具类等非Controller层获取认证信息:

public KeycloakSecurityContext getCurrentContext() {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth instanceof KeycloakAuthenticationToken keycloakAuth) {
        return keycloakAuth.getAccount().getKeycloakSecurityContext();
    }
    throw new IllegalStateException("当前请求无有效Keycloak认证信息");
}

场景2:获取服务端固定身份的AccessToken(密码/客户端凭证模式)

你当前使用keycloak-admin-client的方式本身是可行的,优化点在于将Keycloak客户端实例注册为单例Bean,避免每次请求重复创建,且TokenManager会自动处理Token过期刷新:

步骤1:注册Keycloak客户端Bean

@Configuration
public class KeycloakClientConfig {
    @Value("${keycloak.server-url}")
    private String serverUrl;
    @Value("${keycloak.realm}")
    private String realm;
    @Value("${keycloak.client-id}")
    private String clientId;
    @Value("${keycloak.client-secret}")
    private String clientSecret;
    @Value("${keycloak.account.username}")
    private String username;
    @Value("${keycloak.account.password}")
    private String password;

    @Bean
    public Keycloak keycloakClient() {
        return KeycloakBuilder.builder()
                .serverUrl(serverUrl)
                .realm(realm)
                .grantType(OAuth2Constants.PASSWORD)
                .clientId(clientId)
                .clientSecret(clientSecret)
                .username(username)
                .password(password)
                .build();
    }
}

步骤2:直接注入使用

@Service
public class TokenService {
    @Autowired
    private Keycloak keycloakClient;

    public String getValidAccessToken() {
        // tokenManager自动处理过期刷新,无需手动维护
        return keycloakClient.tokenManager().getAccessToken().getToken();
    }
}

高版本Spring Boot适配方案

如果你使用Spring Boot 2.7+版本,Keycloak官方适配器已停止维护,推荐使用Spring Security原生OAuth2资源服务器配置,获取Token的方式更简洁:

@GetMapping("/token")
public String getToken(BearerTokenAuthentication auth) {
    // 直接获取Token字符串
    String accessToken = auth.getToken().getTokenValue();
    // 直接获取解析后的Claims属性,无需手动反序列化
    Map<String, Object> claims = auth.getTokenAttributes();
    return accessToken;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 22:36:07