Spring Security 之 **WebSecurityConfigurerAdapter** 有多个会怎样

Spring Security 之 WebSecurityConfigurerAdapter 有多个会怎样

同个项目中有多个WebSecurityConfigurerAdapter配置类情况下,会在FilterChainProxyList<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() {
    }
}

总结:

  1. 多个WebSecurityConfigurerAdapter配置类在FilterChainProxy类形成多个Filter过滤链
  2. 请求会根据WebSecurityConfigurerAdapterhttp#antMatcher配置来匹配Filter过滤链
  3. 多个WebSecurityConfigurerAdapterORDER不能相同,否则抛出异常,默认是100
  4. 多个WebSecurityConfigurerAdapter将根据ORDER决定匹配顺序,值越小越前
  5. 多个WebSecurityConfigurerAdapterhttp#antMatche应该由细到粗的顺序配置
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容