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

Spring Boot中使用Keycloak实现无状态JWT的问题求助

Spring Boot + Keycloak 无状态JWT模式配置问题解决

一、空指针异常修复

你的空指针异常是因为未登录时authenticationToken为null(处于匿名认证状态),代码中直接调用了它的getName()方法。解决方法是在获取认证信息前先做非空判断,同时排除匿名认证场景:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && !(authentication instanceof AnonymousAuthenticationToken)) {
    String username = authentication.getName();
    // 后续业务逻辑
}

二、强制登录检查并实现页面重定向

你当前配置的HttpStatusEntryPoint会直接返回401状态码,不会触发重定向到Keycloak登录页。要同时支持浏览器页面重定向登录和API接口无状态JWT验证,需要自定义认证入口点,根据请求类型区分处理:

  1. 自定义AuthenticationEntryPoint:
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    private final LoginUrlAuthenticationEntryPoint loginEntryPoint = new LoginUrlAuthenticationEntryPoint("/oauth2/authorization/keycloak");
    private final HttpStatusEntryPoint apiEntryPoint = new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED);

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        String acceptHeader = request.getHeader("Accept");
        if (acceptHeader != null && acceptHeader.contains("text/html")) {
            // 浏览器页面请求,重定向到Keycloak登录页
            loginEntryPoint.commence(request, response, authException);
        } else {
            // API接口请求,返回401未授权
            apiEntryPoint.commence(request, response, authException);
        }
    }
}
  1. 修改HttpSecurity配置,替换原有的认证入口点:
@Override
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http
        .csrf().disable() // 无状态模式下建议禁用CSRF,或针对API接口单独配置CSRF令牌
        .authorizeRequests()
            .antMatchers("/sso/**", "/error/**", "/css/**", "/contact-us", "/actuator/**", "/isalive/**").permitAll()
            .anyRequest().authenticated()
        .and()
        .oauth2Login()
            .defaultSuccessUrl("/myfirstpage", true)
        .and()
        .exceptionHandling()
            .authenticationEntryPoint(new CustomAuthenticationEntryPoint()) // 使用自定义入口点
        .and()
        .oauth2ResourceServer()
            .jwt();
}

三、配置跳转到Keycloak的/logout接口

要实现登出时跳转到Keycloak的注销页面,需要配置Spring Security的logout逻辑,指定Keycloak的logout端点(需替换为你的Keycloak实例地址、Realm和客户端信息):

@Override
protected void configure(HttpSecurity http) throws Exception {
    // ... 保留其他配置 ...
    http
        .logout()
            .logoutUrl("/logout")
            .logoutSuccessHandler((request, response, authentication) -> {
                // 构建Keycloak注销URL
                String keycloakLogoutUrl = "http://your-keycloak-domain/auth/realms/your-realm/protocol/openid-connect/logout";
                String redirectUri = "http://your-app-domain/"; // 登出后跳转回应用的地址
                String clientId = "your-client-id";
                
                String logoutUrl = String.format("%s?client_id=%s&redirect_uri=%s", keycloakLogoutUrl, clientId, redirectUri);
                response.sendRedirect(logoutUrl);
            })
            .invalidateHttpSession(true)
            .clearAuthentication(true);
}

四、必要的配置补充

确保application.properties中配置了正确的Keycloak OAuth2客户端和资源服务器信息:

# OAuth2 Client配置
spring.security.oauth2.client.registration.keycloak.client-id=your-client-id
spring.security.oauth2.client.registration.keycloak.client-secret=your-client-secret
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.redirect-uri={baseUrl}/login/oauth2/code/keycloak
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://your-keycloak-domain/auth/realms/your-realm

# OAuth2 Resource Server配置
spring.security.oauth2.resource-server.jwt.issuer-uri=http://your-keycloak-domain/auth/realms/your-realm

无状态模式下,Spring Security不会创建HttpSession,需确保业务代码不依赖Session存储信息,所有认证数据都从JWT令牌中解析获取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 09:45:36