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

Spring Cloud Security 403 Forbidden错误排查与修复求助

问题描述

从management service通过自身端口访问advertisement service的以下两个URL时,均返回403 Forbidden错误:

  • http://localhost:9002/api/v1/admin_role/alladvertisements
  • http://localhost:9002/api/v1/user_role/alladvertisements

已分别为admin和user使用Bearer类型的access token,权限规则为admin处理admin_role路径请求、user处理user_role路径请求。

错误返回示例:

{
    "timestamp": "2022-08-31T23:58:15.250+00:00",
    "status": 403,
    "error": "Forbidden",
    "path": "/api/v1/admin_role/alladvertisements"
}
{
    "timestamp": "2022-08-31T23:58:15.250+00:00",
    "status": 403,
    "error": "Forbidden",
    "path": "/api/v1/user_role/alladvertisements"
}

management service的Web Security配置代码:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.csrf().disable();
        http.authorizeRequests()
                .antMatchers("/api/v1/admin_role/*").hasAnyRole("ROLE_ADMIN")
                .antMatchers("/api/v1/user_role/*").hasAnyRole("ROLE_USER")
                .antMatchers("/actuator/health").hasAnyRole("ROLE_ADMIN")
                .antMatchers("/actuator/circuitbreakerevents").hasAnyRole("ROLE_ADMIN")
                .anyRequest()
                .permitAll();

    }

    @Autowired
    protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        KeycloakAuthenticationProvider provider = keycloakAuthenticationProvider();
        provider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(provider);
    }

    @Override
    @Bean
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }
}
修复方案

1. 修正角色前缀匹配问题

SimpleAuthorityMapper默认会给角色自动添加ROLE_前缀,如果你的Keycloak token里的角色已经自带ROLE_前缀,就会出现重复(比如变成ROLE_ROLE_ADMIN),和配置里的ROLE_ADMIN不匹配,直接触发403。

修改configureGlobal方法,关闭自动前缀添加:

@Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    KeycloakAuthenticationProvider provider = keycloakAuthenticationProvider();
    SimpleAuthorityMapper authorityMapper = new SimpleAuthorityMapper();
    // 关闭自动添加ROLE_前缀
    authorityMapper.setPrefix("");
    provider.setGrantedAuthoritiesMapper(authorityMapper);
    auth.authenticationProvider(provider);
}

如果Keycloak里的角色本身不带前缀,也可以把配置里的hasAnyRole("ROLE_ADMIN")改成hasAnyRole("ADMIN"),因为hasAnyRole方法会自动给参数添加ROLE_前缀。

2. 完善资源服务器配置

因为是微服务间用Bearer token调用,需要确保management service的配置文件(application.yml/application.properties)里添加了正确的Keycloak资源服务器配置:

keycloak:
  resource: your-client-id
  auth-server-url: http://your-keycloak-address/auth
  realm: your-realm-name
  bearer-only: true

bearer-only: true表示服务只接受Bearer token,不处理登录跳转,适配微服务间的调用场景。

3. 调整路径匹配规则

当前的/api/v1/admin_role/*只能匹配单层子路径,如果你需要匹配admin_role下的所有层级路径(比如后续可能有子接口),改成/api/v1/admin_role/**:

http.authorizeRequests()
        .antMatchers("/api/v1/admin_role/**").hasAnyRole("ROLE_ADMIN")
        .antMatchers("/api/v1/user_role/**").hasAnyRole("ROLE_USER")
        // 其余配置保持不变

4. 验证Token中的角色信息

用JWT解析工具(比如jwt.io)拆解你的Bearer token,确认realm_access.roles字段里包含对应的ADMIN或USER角色,且格式和配置里的规则匹配(比如是否带ROLE_前缀)。

5. 检查Keycloak客户端配置

确保Keycloak中对应客户端的范围设置正确,已经包含了需要的角色,且token生成时会把这些角色信息写入其中。

内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 19:06:26