spring gateway ,spring security集成,webfilter执行两次的问题处理
1.问题说明
spring gateway ,spring security集成时候, 使用@Component注册filter
@Component
public class XFilter implements WebFilter {
又在SecurityWebFilterChain里配置了filter
@Autowired
XFilter xfilter;
@Bean
SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception {
http .addFilterBefore(xfilter, SecurityWebFiltersOrder.CORS)
导致filter会执行两次
2.解决方法
1.不使用@Component注册filter,只在SecurityWebFilterChain里配置,如果要使用bean的话,需要通过构造器来注入,或者直接注入ApplicationContext
public class XFilter implements WebFilter {
private DataCache dataCache;
public XFilter(DataCache dataCache){
this.dataCache = dataCache;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return null;
}
}
@Autowired
DataCache dataCache;
@Bean
SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception {
http .addFilterBefore(new XFilter(dataCache), SecurityWebFiltersOrder.CORS)
2.采用类似org.springframework.web.filter.OncePerRequestFilter的处理方法来处理
public abstract class AbstractMatchWebFilter implements WebFilter{
public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
if (!hasFilter(serverWebExchange) && shouldFilter(serverWebExchange) && !shouldNotFilter(serverWebExchange)) {
signFilter(serverWebExchange);
return doFilter(serverWebExchange,webFilterChain);
} else {
return webFilterChain.filter(serverWebExchange);
}
}
protected String getAlreadyFilteredAttributeName() {
return getClass().getName() + ALREADY_FILTERED_SUFFIX;
}
private boolean hasFilter(ServerWebExchange exchange){
Boolean sign = (Boolean) exchange.getAttributes().get(getAlreadyFilteredAttributeName());
return Boolean.TRUE.equals(sign);
}
private void signFilter(ServerWebExchange exchange){
exchange.getAttributes().put(getAlreadyFilteredAttributeName(),Boolean.TRUE);
}
protected abstract Mono<Void> doFilter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain);
protected boolean shouldNotFilter(ServerWebExchange serverWebExchange) {
return false;
}
protected boolean shouldFilter(ServerWebExchange serverWebExchange) {
return true;
}
protected boolean match(String requestUrl,String authHref){
return antPathMatcher.match(authHref,requestUrl);
}
}
实现原理是在filter执行前检查在exchange Attributes里边的一个标记,如果没有就是第一次执行,添加此标记,如果有就不执行。此抽象类可以直接继承使用,还可以实现shouldNotFilter,shouldFilter来控制filter是否执行
|