如何在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
相关产品推荐
相关产品推荐

