Spring Security 之 WebSecurityConfigurerAdapter 有多个会怎样
同个项目中有多个WebSecurityConfigurerAdapter配置类情况下,会在FilterChainProxy中List<SecurityFilterChain> filterChains形成多个独立过滤链
当有请求时,则会按顺序匹配相应的过滤链,先匹配先使用
FilterChainProxy
Spring Security中的过滤链代理类,其存储了List<SecurityFilterChain>多个过滤链
public class FilterChainProxy extends GenericFilterBean {
private List<SecurityFilterChain> filterChains;
/**
* 进行过滤
*/
private void doFilterInternal(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
FirewalledRequest fwRequest = firewall
.getFirewalledRequest((HttpServletRequest) request);
HttpServletResponse fwResponse = firewall
.getFirewalledResponse((HttpServletResponse) response);
List<Filter> filters = getFilters(fwRequest);
if (filters == null || filters.size() == 0) {
if (logger.isDebugEnabled()) {
logger.debug(UrlUtils.buildRequestUrl(fwRequest)
+ (filters == null ? " has no matching filters"
: " has an empty filter list"));
}
fwRequest.reset();
chain.doFilter(fwRequest, fwResponse);
return;
}
VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);
vfc.doFilter(fwRequest, fwResponse);
}
/**
* 将请求匹配到具体的过滤链上
*/
private List<Filter> getFilters(HttpServletRequest request) {
for (SecurityFilterChain chain : filterChains) {
if (chain.matches(request)) {
return chain.getFilters();
}
}
return null;
}
}
public interface SecurityFilterChain {
boolean matches(HttpServletRequest request);
List<Filter> getFilters();
}
其中HttpSecurity#antMatcher("") 与 Http#authorizeRequests()#antMatchers("") 对于过滤链的作用,以及区别
HttpSecurity#antMatcher("")
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/hello/**") // 匹配所有/hello/开头的
.authorizeRequests() //
.antMatchers("/hello/doHello").permitAll() // 对子路径进行细化
.antMatchers("/hello/doHello2").authenticated(); // 对子路径进行细化
}
以上只会处理/hello开头请求,http#antMatcher 最后配置的生效,其中代码逻辑如下
public HttpSecurity antMatcher(String antPattern) {
return requestMatcher(new AntPathRequestMatcher(antPattern));
}
public HttpSecurity requestMatcher(RequestMatcher requestMatcher) {
this.requestMatcher = requestMatcher;
return this;
}
赋值给this.requestMatcher变量,因此多次赋值只会最后一个生效
Http#authorizeRequests()#antMatchers("")
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/hello").permitAll();
}
此配置等同于,即此链匹配所有请求
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().antMatchers("/hello").permitAll();
}
antMatcher实现
private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE;
public HttpSecurity antMatcher(String antPattern) {
return requestMatcher(new AntPathRequestMatcher(antPattern));
}
public HttpSecurity requestMatcher(RequestMatcher requestMatcher) {
this.requestMatcher = requestMatcher;
return this;
}
AnyRequestMatcher 具体代码如下,即匹配所有请求
public final class AnyRequestMatcher implements RequestMatcher {
public static final RequestMatcher INSTANCE = new AnyRequestMatcher();
public boolean matches(HttpServletRequest request) {
return true;
}
@Override
@SuppressWarnings("deprecation")
public boolean equals(Object obj) {
return obj instanceof AnyRequestMatcher
|| obj instanceof org.springframework.security.web.util.matcher.AnyRequestMatcher;
}
@Override
public int hashCode() {
return 1;
}
@Override
public String toString() {
return "any request";
}
private AnyRequestMatcher() {
}
}
总结:
- 多个WebSecurityConfigurerAdapter配置类在FilterChainProxy类形成多个Filter过滤链
- 请求会根据WebSecurityConfigurerAdapter中http#antMatcher配置来匹配Filter过滤链
- 多个WebSecurityConfigurerAdapter的ORDER不能相同,否则抛出异常,默认是100
- 多个WebSecurityConfigurerAdapter将根据ORDER决定匹配顺序,值越小越前
- 多个WebSecurityConfigurerAdapter的http#antMatche应该由细到粗的顺序配置