Java 模块化Spring安全性WebFilterChain
我们的Spring安全配置文件正在变得越来越大,我们希望将其分解为更小的部分。现在我们有以下几点:Java 模块化Spring安全性WebFilterChain,java,spring,spring-security,spring-webflux,Java,Spring,Spring Security,Spring Webflux,我们的Spring安全配置文件正在变得越来越大,我们希望将其分解为更小的部分。现在我们有以下几点: public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { http.securityMatcher(ServerWebExchangeMatchers.pathMatchers("/api/**")) .authenticationManager(this.auth
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http.securityMatcher(ServerWebExchangeMatchers.pathMatchers("/api/**"))
.authenticationManager(this.authenticationManager);
http.authorizeExchange()
.pathMatchers(HttpMethod.GET, "/api/serviceA/**")
.hasAuthority("PROP_A");
http.authorizeExchange()
.pathMatchers(HttpMethod.GET, "/api/serviceB/**")
.hasAuthority("PROP_B");
http.authorizeExchange().pathMatchers(HttpMethod.POST, "/api/login", "/api/logout", "/api/forgotPassword", "/api/confirmForgotPassword").permitAll();
http.csrf()
.disable()
.formLogin()
.authenticationEntryPoint(new HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED))
.requiresAuthenticationMatcher(
ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, "/api/login"))
.authenticationFailureHandler(CustomSpringSecurity::onAuthenticationFailure)
.authenticationSuccessHandler(CustomSpringSecurity::onAuthenticationSuccess)
.and()
.logout()
.logoutUrl("/api/logout")
.logoutSuccessHandler(new CustomLogoutSuccessHandler(HttpStatus.OK));
final SecurityWebFilterChain build = http.build();
build
.getWebFilters()
.collectList()
.subscribe(
webFilters -> {
for (WebFilter filter : webFilters) {
if (filter instanceof AuthenticationWebFilter) {
AuthenticationWebFilter awf = (AuthenticationWebFilter) filter;
awf.setServerAuthenticationConverter(CustomSpringSecurity::convert);
}
}
});
return build;
}
我们想使用securityMatcher
来突破/api/seviceA/**
和/api/sevice/**
来拥有SecurityWebFilterChain@Beans
然而,我们的问题是配置中存在的额外配置数量。我们希望最终结果如下所示
public SecurityWebFilterChain securityWebFilterChainForServiceA(ServerHttpSecurity http) {
http.securityMatcher(ServerWebExchangeMatchers.pathMatchers("/api/serviceA/**"));
http.authorizeExchange()
.pathMatchers(HttpMethod.GET, "/api/serviceA/**")
.hasAuthority("PROP_A");
return http.build();
}
我们希望端点的所有其他配置都是隐式的
如何在Spring Security中实现这样的模块化?您可以指定如下接口:
public interface HttpSecurityConfig {
Consumer<ServerHttpSecurity> configuration();
}
很好,它可以工作,但是您必须删除http.securityMatcher(ServerWebExchangeMatchers.pathMatchers(“/api/serviceA/**”);因为每一份上只能有一份。
@Component
public class ServiceASecurityConfig implements HttpSecurityConfig {
@Override
public Consumer<ServerHttpSecurity> configuration() {
return (http) -> {
http.authorizeExchange()
.pathMatchers(HttpMethod.GET, "/api/serviceA/**")
.hasAuthority("PROP_A");
};
}
}
@Component
public class ServiceBSecurityConfig implements HttpSecurityConfig {
@Override
public Consumer<ServerHttpSecurity> configuration() {
return (http) -> {
http.authorizeExchange()
.pathMatchers(HttpMethod.GET, "/api/serviceB/**")
.hasAuthority("PROP_B");
};
}
}
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http, final List<HttpSecurityConfig> httpConfigurations) {
http.securityMatcher(ServerWebExchangeMatchers.pathMatchers("/api/**"))
.authenticationManager(this.authenticationManager);
// This line replaces the individual configurations in your original question
httpConfigurations.forEach(config -> config.configuration().accept(http));
http.authorizeExchange().pathMatchers(HttpMethod.POST, "/api/login", "/api/logout", "/api/forgotPassword", "/api/confirmForgotPassword").permitAll();
http.csrf()
.disable()
.formLogin()
.authenticationEntryPoint(new HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED))
.requiresAuthenticationMatcher(
ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, "/api/login"))
.authenticationFailureHandler(CustomSpringSecurity::onAuthenticationFailure)
.authenticationSuccessHandler(CustomSpringSecurity::onAuthenticationSuccess)
.and()
.logout()
.logoutUrl("/api/logout")
.logoutSuccessHandler(new CustomLogoutSuccessHandler(HttpStatus.OK));
final SecurityWebFilterChain build = http.build();
build
.getWebFilters()
.collectList()
.subscribe(
webFilters -> {
for (WebFilter filter : webFilters) {
if (filter instanceof AuthenticationWebFilter) {
AuthenticationWebFilter awf = (AuthenticationWebFilter) filter;
awf.setServerAuthenticationConverter(CustomSpringSecurity::convert);
}
}
});
return build;
}