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

Spring Boot集成Keycloak SSO时Principal对象为空问题求助

我之前也碰到过类似的问题,明明Keycloak日志显示认证成功了,但Spring控制器里就是拿不到Principal,给你几个靠谱的排查和解决方向:

1. 必须配置Spring Security的Keycloak适配类

Keycloak的Spring Boot Starter依赖Spring Security才能把认证信息绑定到Spring上下文里,你需要创建一个继承KeycloakWebSecurityConfigurerAdapter的配置类,确保认证流程被正确接入:

import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;

@KeycloakConfiguration
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    // 配置认证提供者,确保角色映射正确
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        KeycloakAuthenticationProvider authProvider = keycloakAuthenticationProvider();
        // 这里可以调整角色前缀,比如去掉默认的ROLE_,根据你的需求来
        authProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(authProvider);
    }

    // 配置会话策略,如果不需要session可以用Null策略
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new NullAuthenticatedSessionStrategy();
    }

    // 配置Http安全规则,和你application.yml里的security-constraints对应上
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.authorizeRequests()
                .antMatchers("/v2/auth/keycloak").hasRole("USER")
                .anyRequest().permitAll();
    }
}

2. 用@AuthenticationPrincipal直接注入KeycloakPrincipal

不要直接用Principal或者从HttpServletRequest里拿,试试Spring Security提供的@AuthenticationPrincipal注解,它能直接帮你注入认证后的KeycloakPrincipal对象:

import org.keycloak.KeycloakPrincipal;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RestController
public class AuthController {
    private static final Logger log = LoggerFactory.getLogger(AuthController.class);

    @GetMapping("/v2/auth/keycloak")
    public void authUsingKeycloak(@AuthenticationPrincipal KeycloakPrincipal<?> principal) {
        if (principal != null) {
            String username = principal.getName();
            String userId = principal.getKeycloakSecurityContext().getToken().getSubject();
            log.info("User {} (ID: {}) logged using Keycloak", username, userId);
        } else {
            log.warn("Principal is still null!");
        }
    }
}

3. 检查角色配置和版本兼容性

  • 确认你的Keycloak用户确实被分配了USER角色(不管是Realm级别还是Client级别,根据keycloak.use-resource-role-mappings的配置来),如果角色不匹配,认证后也可能无法正确绑定Principal。
  • 检查Spring Boot和Keycloak版本的兼容性:你用的Keycloak 13.0.1对应的Spring Boot版本建议是2.4.x,如果你的Spring Boot版本太高(比如2.5+),可能需要调整Keycloak适配器的配置,或者升级Keycloak版本。

4. 排查是否有其他Security配置干扰

如果你还有其他自定义的Spring Security配置类,比如继承WebSecurityConfigurerAdapter的其他类,可能会覆盖Keycloak的配置,导致认证信息无法正确传递。确保只有一个Keycloak相关的Security配置类生效。

按照上面的步骤调整后,应该就能正确拿到Principal对象了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 06:56:08