Spring Webflux 安全过滤器链 JwtIssuerReactiveAuthenticationManagerResolver 与 jwt 转换器

问题描述 投票:0回答:1

我有一个为多租户配置的简单安全过滤器链。但是,我无法添加我的客户 jwtConverter。

这是设置

 @Bean
    SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http,  Converter<Jwt, Mono<AbstractAuthenticationToken>> jwtAuthenticationConverter) {
        JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver =
                JwtIssuerReactiveAuthenticationManagerResolver
                        .fromTrustedIssuers("issuer1", "issuer2");

        http
                .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
                .csrf(ServerHttpSecurity.CsrfSpec::disable)
                .authorizeExchange(spec -> spec
                        .pathMatchers(
                                "/api/v1/profile/public/**",
                                "/api/docs/**",
                                "/swagger/**"
                        ).permitAll()
                        .anyExchange()
                        .authenticated()
                )
                .oauth2ResourceServer(oauth2 -> oauth2.authenticationManagerResolver(authenticationManagerResolver));
        return http.build();
    }

当我添加 jwtConverter 时

 .oauth2ResourceServer(oauth2 ->
                        oauth2
                                .jwt(jwtSpec -> jwtSpec.jwtAuthenticationConverter(jwtAuthenticationConverter))
                                .authenticationManagerResolver(authenticationManagerResolver)

                )

我收到错误如果配置了authenticationManagerResolver(),那么它优先于任何jwt()或opaqueToken()配置

如何在 Spring webflux 3.2.1 中解决此问题?

spring-boot jwt spring-webflux
1个回答
0
投票

嗯,在对过去提出的 github 问题进行了一些交叉检查之后,我成功创建了一个自定义

JwtIssuerReactiveAuthenticationManagerResolver
,其中
CustomAuthenticationManager
具有
authenticate
方法,可以扩展以允许自定义身份验证转换器。

这是我的解决方案

简单的自定义身份验证转换器

public class CustomAuthenticationConverter {
    private static final String ROLES = "roleName";
    private static final String ROLE_PREFIX = "ROLE_";

    public Mono<Authentication> convertJwtToAuthentication(Jwt jwt) {
        Collection<GrantedAuthority> authorities = extractAuthoritiesFromJwt(jwt);
        return Mono.just(new JwtAuthenticationToken(jwt, authorities, jwt.getClaimAsString("userPublicId")));
    }

    private Collection<GrantedAuthority> extractAuthoritiesFromJwt(Jwt jwt) {
        var realmRoles = realmRoles(jwt);

        return realmRoles
                .stream()
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toSet());
    }

    private List<String> realmRoles(Jwt jwt) {
        return Optional.of(ROLE_PREFIX.concat(jwt.getClaimAsString(ROLES)))
                .map(List::of)
                .orElse(emptyList());
    }
}

自定义身份验证管理器

public class CustomAuthenticationManager implements ReactiveAuthenticationManager {

    private final ReactiveJwtDecoder decoder;

    public CustomAuthenticationManager(ReactiveJwtDecoder decoder) {
        this.decoder = decoder;
    }

    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        // Implement custom authentication logic here
        BearerTokenAuthenticationToken token = (BearerTokenAuthenticationToken) authentication;
        Mono<Jwt> jwtMono = decoder.decode(token.getToken());

        return jwtMono.flatMap(jwt -> new CustomAuthenticationConverter().convertJwtToAuthentication(jwt));
    }
}

JwtIssuerReactiveAuthenticationManagerResolver

@Bean
    public JwtIssuerReactiveAuthenticationManagerResolver jwtIssuerReactiveAuthenticationManagerResolver() {
        Map<String, ReactiveAuthenticationManager> managers = new HashMap<>();
        for (String issuer : trustedIssuers) {
            ReactiveJwtDecoder decoder = ReactiveJwtDecoders.fromIssuerLocation(issuer);
            managers.put(issuer, new CustomAuthenticationManager(decoder));
        }
        return new JwtIssuerReactiveAuthenticationManagerResolver(issuer -> Mono.justOrEmpty(managers.get(issuer)));
    }

在SecurityWebFilterChain中添加解析器

.oauth2ResourceServer(oauth2 -> oauth2.authenticationManagerResolver(jwtIssuerReactiveAuthenticationManagerResolver()));

当然,您需要一份

trustedIssuers
的列表。

© www.soinside.com 2019 - 2024. All rights reserved.