首页 > 解决方案 > 如何在 Spring Cloud Gateway 上获得角色

问题描述

我有一个 Spring Cloud Gateway 和一个微服务

我正在使用带有 Keycloak 的 OAuth2

API Gateway 是我的 OAuth2 客户端,它提供安全页面并将请求重定向到微服务

我需要授权访问渲染器一页“/backoffice”,但是当我使用 hasRole 方法授权用户接收访问被拒绝时。

这是因为 keycloak 使用以下模式生成访问令牌:

来自 Keycloak 的访问令牌

这是我的网关 SecurityWebFilterChain

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
    
    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        
        http.csrf().disable();
        
        http.
            authorizeExchange()
            .pathMatchers("/backoffice/**").hasRole("approver")
            .anyExchange().permitAll()
            .and()
            .oauth2Login()
            .and()
            .oauth2Client();
        
        return http.build();
        
    }
}

我尝试使用与微服务相同的方法,但我收到 401 Unauthorized... 我尝试使用 @Order 有两个过滤器但不起作用

  // Microservice's SecurityWebFilterChain
    @Bean
        public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
            
            http
                .csrf().disable()
                .authorizeExchange(exchanges -> 
                    exchanges
                        .pathMatchers("/{id}/decision").hasRole("ROLE_user")
                        .anyExchange().permitAll())
                        .oauth2ResourceServer(oauth2 ->
                            oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(grantedAuthoritiesExtractor())));      
            
            return http.build();
        }
        
        Converter<Jwt, Mono<AbstractAuthenticationToken>> grantedAuthoritiesExtractor() {
            JwtAuthenticationConverter jwtAuthenticationConverter =
                    new JwtAuthenticationConverter();
            
            jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(new GrantedAuthoritiesExtractor());
            
            return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
        }
        
        static class GrantedAuthoritiesExtractor implements Converter<Jwt, Collection<GrantedAuthority>> {
    
            @Override
            public Collection<GrantedAuthority> convert(Jwt jwt) {
                
                var realm_access = (Map<String, List<String>>) jwt.getClaims().getOrDefault("realm_access", Collections.emptyMap());
                
                return realm_access.get("roles").stream()
                    .map(role -> "ROLE_".concat(role))
                    .map(SimpleGrantedAuthority::new)
                    .collect(Collectors.toList());
            }
            
        }

我可以在同一个应用程序中同时拥有两者,有冲突吗?

标签: spring-securityspring-security-oauth2

解决方案


推荐阅读