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

Spring Webflux网关基于Keycloak角色认证403问题排查

排查Spring Webflux ApiGateway + Keycloak 403权限问题

以下是几个常见的排查方向和解决方法:

1. 确认JwtAuthenticationConverter配置适配Webflux环境

Webflux的安全配置逻辑和Servlet环境不同,必须在ServerHttpSecurity中正确注册转换器,且确保转换器能准确提取roles声明:

@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {
    JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
    // 指定从roles字段获取权限
    grantedAuthoritiesConverter.setAuthoritiesClaimName("roles");
    // 移除默认的ROLE_前缀,让权限直接为ADMIN
    grantedAuthoritiesConverter.setAuthorityPrefix("");

    JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
    converter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
    return converter;
}

// 安全配置中注册转换器
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    http
        .authorizeExchange(exchanges -> exchanges
            .pathMatchers("/api/user/**").hasAuthority("ADMIN")
            .anyExchange().authenticated()
        )
        .oauth2ResourceServer(oauth2 -> oauth2
            .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter()))
        );
    return http.build();
}

重点检查:

  • 转换器是否被正确绑定到oauth2ResourceServer().jwt()配置中
  • setAuthorityPrefix("")是否生效,避免权限被自动加上ROLE_前缀变成ROLE_ADMIN

2. 权限表达式使用是否正确

如果转换器输出的权限是ADMIN(无前缀),必须用hasAuthority("ADMIN"),不能用hasRole("ADMIN")——因为hasRole会自动给权限添加ROLE_前缀,导致系统去匹配不存在的ROLE_ADMIN权限,最终返回403。

3. 验证JWT中的角色格式

再次解码JWT,确认roles声明的细节:

  • 是否为数组格式:比如"roles": ["ADMIN"]才是正确的,若为"roles": "ADMIN"(单个字符串),转换器可能无法解析为有效权限
  • 角色名称是否完全匹配:检查大小写、是否有多余空格,比如Keycloak中角色是admin但JWT里是ADMIN,会导致匹配失败

4. 检查路径匹配规则的顺序

Webflux的authorizeExchange是按配置顺序匹配路径的,如果把通用规则(比如anyExchange().authenticated())放在具体路径规则前面,会导致/api/user/**的权限规则不生效。必须把更具体的路径规则放在前面:

// 正确顺序:先匹配具体路径,再匹配通用路径
.authorizeExchange(exchanges -> exchanges
    .pathMatchers("/api/user/**").hasAuthority("ADMIN")
    .anyExchange().authenticated()
)

5. 打印Authentication对象验证权限

添加全局过滤器,打印当前请求的Authentication信息,确认权限是否正确加载:

@Component
public class AuthLoggingFilter implements WebFilter {
    private static final Logger log = LoggerFactory.getLogger(AuthLoggingFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        return exchange.getPrincipal()
            .doOnNext(principal -> {
                if (principal instanceof JwtAuthenticationToken jwtToken) {
                    log.info("当前用户权限列表: {}", jwtToken.getAuthorities());
                }
            })
            .then(chain.filter(exchange));
    }
}

启动服务后请求/api/user/**,查看日志中是否包含ADMIN权限。如果没有,说明转换器未正确提取权限,回到第一步检查配置。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 12:46:07