我有一个为多租户配置的简单安全过滤器链。但是,我无法添加我的客户 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 中解决此问题?
嗯,在对过去提出的 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
的列表。