在SpringCloud Gateway网关中,必不可少的就是filter了,网关中的filter是分两层走的,先走一层是bean的filter,再走一层普通的filter。具体什么意思,下面我们一起来看下。
一、带bean的filter。
刚开始初始化的时候,会加载HttpHandlerAutoConfiguration类中的bean,HttpHandler,如下:
@Bean
public HttpHandler httpHandler() {
return WebHttpHandlerBuilder.applicationContext(this.applicationContext)
.build();
}
public static WebHttpHandlerBuilder applicationContext(ApplicationContext context) {
WebHttpHandlerBuilder builder = new WebHttpHandlerBuilder(
context.getBean(WEB_HANDLER_BEAN_NAME, WebHandler.class), context);
// Autowire lists for @Bean + @Order
SortedBeanContainer container = new SortedBeanContainer();
context.getAutowireCapableBeanFactory().autowireBean(container);
在上面代码的最后一行,去获取了了SortedBeanContainer类型的bean,而sortedBeanContainer依赖了如下两种类型的bean:
@Autowired(required = false)
public void setFilters(List<WebFilter> filters) {
this.filters = filters;
}
@Autowired(required = false)
public void setExceptionHandlers(List<WebExceptionHandler> exceptionHandlers) {
this.exceptionHandlers = exceptionHandlers;
}
而在依赖的bean类型中,一个Bean类型的filter为:WebFilterChainProxy,bean类型的WebFilter和非Bean类型的WebFilter的调用就发生在这个类上,
@Bean(SPRING_SECURITY_WEBFILTERCHAINFILTER_BEAN_NAME)
@Order(value = WEB_FILTER_CHAIN_FILTER_ORDER)
public WebFilterChainProxy springSecurityWebFilterChainFilter() {
return new WebFilterChainProxy(getSecurityWebFilterChains());
}
这个方法在类:WebFluxSecurityConfiguration中,这个类有个属性:
@Autowired(required = false)
private List<SecurityWebFilterChain> securityWebFilterChains;
如果这个类型的bean存在的话,就会在WebFilterChainProxy的filter方法中被调用:
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return Flux.fromIterable(this.filters)
.filterWhen( securityWebFilterChain -> securityWebFilterChain.matches(exchange))
.next()
.switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
.flatMap( securityWebFilterChain -> securityWebFilterChain.getWebFilters()
.collectList()
)
.map( filters -> new FilteringWebHandler(webHandler -> chain.filter(webHandler), filters))
.map( handler -> new DefaultWebFilterChain(handler) )
.flatMap( securedChain -> securedChain.filter(exchange));
}
二、不带bean的filter
就是如果我们自定义了SecurityWebFilterChain类型的bean的话,那么我们就可以使用自定义的调用链了。类似如下:
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.authorizeExchange()
.anyExchange().authenticated()
.and().csrf().disable()
.httpBasic().disable()
.formLogin().disable()
.logout().disable()
.requestCache().disable();
http.addFilterAt(authenticationWebFilter(), SecurityWebFiltersOrder.FORM_LOGIN);
//rewrite路由转发
http.addFilterAt(rewriteWebFilter(), SecurityWebFiltersOrder.AUTHENTICATION);
http.addFilterAt(authorizationWebFilter(),SecurityWebFiltersOrder.AUTHENTICATION);
return http.build();
}
三、调用的地方
在bean都实例化后,实例化的Bean类型的filter就放入了WebHttpHandlerBuilder的filters属性中,然后我们回到最初获取HttpHandler()方法:
@Bean
public HttpHandler httpHandler() {
return WebHttpHandlerBuilder.applicationContext(this.applicationContext)
.build();
}
builder()方法中有这么一行方法:
decorated = new FilteringWebHandler(this.webHandler, this.filters);
可以看到将我们获取的filter类型的bean,放入到了FilteringWebHandler的属性中,而这个FilteringWebHandler中的handle()方法就是我们过滤器走的方法。