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

如何在Spring Boot集成Keycloak时自定义401和403 HTTP响应?

如何自定义Keycloak相关的401/403错误响应

假设你是基于Spring Boot + Spring Security整合Keycloak的场景,以下几种方案可以实现自定义响应:

方案1:全局异常处理器(最简便)

直接捕获Keycloak抛出的认证/授权异常,自定义响应体结构:

@RestControllerAdvice
public class CustomAuthExceptionHandler {

    // 处理令牌无效/过期的401场景
    @ExceptionHandler(OAuth2AuthenticationException.class)
    public ResponseEntity<Map<String, Object>> handleInvalidToken(OAuth2AuthenticationException ex) {
        Map<String, Object> response = new HashMap<>();
        response.put("code", "INVALID_OR_EXPIRED_TOKEN");
        response.put("message", "令牌无效或已过期,请重新登录");
        response.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
    }

    // 处理访问被拒绝的403场景
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<Map<String, Object>> handleAccessDenied(AccessDeniedException ex) {
        Map<String, Object> response = new HashMap<>();
        response.put("code", "ACCESS_DENIED");
        response.put("message", "您没有权限访问该资源");
        // 不需要堆栈的话直接删掉这行
        response.put("error_detail", ex.getMessage());
        
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body(response);
    }
}

这个方案无需修改底层过滤器,直接通过Spring的全局异常捕获机制覆盖默认响应,灵活度高,还能自由控制是否返回异常细节。

方案2:扩展Keycloak认证过滤器(底层控制)

如果需要在令牌校验阶段就直接返回自定义响应,绕过默认的无体401,可以扩展Keycloak的认证过滤器:

@Component
public class CustomKeycloakAuthFilter extends KeycloakAuthenticationProcessingFilter {

    public CustomKeycloakAuthFilter(KeycloakAuthenticationManager authManager,
                                    KeycloakDeploymentResolver deploymentResolver) {
        super(authManager, deploymentResolver);
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                              AuthenticationException failed) throws IOException {
        // 自定义401响应内容
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        
        Map<String, Object> responseBody = new HashMap<>();
        responseBody.put("code", "TOKEN_VALIDATION_FAILED");
        responseBody.put("message", "令牌校验失败,请检查令牌有效性");
        responseBody.put("timestamp", System.currentTimeMillis());
        
        new ObjectMapper().writeValue(response.getWriter(), responseBody);
    }
}

同理,若要自定义403响应,可以扩展KeycloakAuthorizationFilter,重写其授权失败的处理逻辑。

方案3:Spring Security配置中统一处理

在Spring Security的配置类里,直接配置认证/授权异常的处理器:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http
            .exceptionHandling()
                // 自定义401响应
                .authenticationEntryPoint((request, response, authEx) -> {
                    response.setStatus(HttpStatus.UNAUTHORIZED.value());
                    response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                    String respJson = "{\"code\":\"UNAUTHORIZED\",\"message\":\"令牌无效或已过期\",\"timestamp\":" + System.currentTimeMillis() + "}";
                    response.getWriter().write(respJson);
                })
                // 自定义403响应
                .accessDeniedHandler((request, response, accessDeniedEx) -> {
                    response.setStatus(HttpStatus.FORBIDDEN.value());
                    response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                    String respJson = "{\"code\":\"FORBIDDEN\",\"message\":\"无访问权限\",\"detail\":\"" + accessDeniedEx.getMessage() + "\"}";
                    response.getWriter().write(respJson);
                });
    }

    // 以下是Keycloak整合Spring Security的必要配置
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        KeycloakAuthenticationProvider authProvider = keycloakAuthenticationProvider();
        authProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(authProvider);
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Bean
    public KeycloakConfigResolver keycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }
}

这种方案把异常处理和Security配置绑定在一起,适合需要统一管理所有安全相关响应的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 11:31:04