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

使用Keycloak安全加固Spring Boot应用未正常返回403错误问题排查

问题根因

你当前的配置将Keycloak客户端设置为了public-client,这类客户端默认针对未认证请求会触发重定向跳转到Keycloak登录页,不会直接返回状态码。你用curl默认不跟随重定向时,就会看起来没有返回内容。同时你的安全配置没有显式指定API场景下的异常处理规则,也会导致状态码返回不符合预期。

解决方案

1. 修改application.properties配置

将客户端模式改为仅接受Bearer令牌的资源服务模式,同时删除和Java配置冲突的路径约束配置:

# 删掉原来的 keycloak.public-client=true 替换为下面的配置
keycloak.bearer-only=true
# 删掉下面这两行,避免和SecurityConfig的Java配置冲突
# keycloak.security-constraints[0].authRoles[0]=user
# keycloak.security-constraints[0].securityCollections[0].patterns[0]=/test

2. 调整SecurityConfig配置

显式禁用CSRF(API服务不需要),配置异常处理直接返回状态码,不触发重定向:

@KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider  = keycloakAuthenticationProvider();
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

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

    // 新增Bean:配置未认证入口直接返回401,不跳转登录页
    @Bean
    @Override
    protected AuthenticationEntryPoint authenticationEntryPoint() {
        return new KeycloakAuthenticationEntryPoint(adapterDeploymentContext()) {
            @Override
            protected void commenceUnauthenticated(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "未携带有效访问令牌");
            }
        };
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http
            // API服务禁用CSRF
            .csrf().disable()
            // 配置异常处理,无权限时返回403
            .exceptionHandling()
                .accessDeniedHandler((request, response, accessDeniedException) -> {
                    response.sendError(HttpServletResponse.SC_FORBIDDEN, "无访问权限");
                })
            .and()
            .authorizeRequests()
                .anyRequest().authenticated();
    }
    
}

3. 验证效果

修改配置后重启服务,用不带token的curl请求测试,就能正常收到401状态码和错误提示:

curl -v localhost:8080/test/protected --insecure

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 16:00:00