美文网首页
Spring Security解析三:SecurityFilte

Spring Security解析三:SecurityFilte

作者: 一根线条 | 来源:发表于2020-03-08 16:54 被阅读0次

Spring Security解析一:安全配置过程概览章节我们知道了springSecurityFilterChain的大致构建过程,这里进步探讨其创建的细节。

springSecurityFilterChain的创建是关键,当创建完该Bean以后,再结合SpringBoot的自动化装配过程完成了在Servlet容器中注册,从而达到了对请求的拦截处理。

WebSecurity的作用就是构建springSecurityFilterChain,通过前面过程的配置,最后执行其buid()方法完成了构建过程。WebSecurity的继承关系如下:

WebSecurity

WebSecurityConfiguration中完成springSecurityFilterChain的构建,如下所示:

@Configuration(proxyBeanMethods = false)
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
    private WebSecurity webSecurity;
    //收集保存所有的SecurityConfigurer配置
    private List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers;

    /**
     * Creates the Spring Security Filter Chain 
     *【默认的Filter的名称为springSecurityFilterChain】
     * 注意:在SpringBoot中通过自动化配置会通过该名称来创建DelegatingFilterProxyRegistrationBean,
     * 从而在初始化阶段被注册到Servlet容器中。
     */
    @Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
    public Filter springSecurityFilterChain() throws Exception {
        //判断当前IOC中是否有SecurityConfigurer,如果没有则使用WebSecurityConfigurerAdapter作为默认配置
        //webSecurityConfigurers由上面的setFilterChainProxySecurityConfigurer方法执行后得出
        boolean hasConfigurers = webSecurityConfigurers != null
                && !webSecurityConfigurers.isEmpty();
        if (!hasConfigurers) {  //如果没有找到SecurityConfigurer类型的Bean则执行默认配置
            //使用WebSecurityConfigurerAdapter作为配置
            WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
                    .postProcess(new WebSecurityConfigurerAdapter() {
                    });
            //添加到WebSecurity中
            webSecurity.apply(adapter);
        }
        //构建过滤器链【会执行本类的performBuild方法完成Filter的创建】
        return webSecurity.build();
    }
}

接着进一步探究WebSecurity的build方法的执行细节。


在执行WebSecurity实例的build时,会调用父类AbstractConfiguredSecurityBuilder的doBuild()方法,该方法是个模板方法,定义如下:

public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>
        extends AbstractSecurityBuilder<O> {

    @Override
    protected final O doBuild() throws Exception {
        synchronized (configurers) {
            buildState = BuildState.INITIALIZING;
            //该方法默认什么都没做
            beforeInit();  
            //以WebSecurity自己为参数调用SecurityConfigurer的init方法
            init();

            buildState = BuildState.CONFIGURING;

            //该方法默认什么都没做
            beforeConfigure();
            //以WebSecurity自己为参数调用SecurityConfigurer的configure方法
            configure();

            buildState = BuildState.BUILDING;

            //子类中执行Filter的构建操作
            O result = performBuild();

            buildState = BuildState.BUILT;

            return result;
        }
    }

    //供子类实现(WebSecurity)
    protected abstract O performBuild() throws Exception;
}

从上到下,我们探究下init()与configure()方法都做了啥

public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>
        extends AbstractSecurityBuilder<O> {

    //以WebSecurity自己为参数调用SecurityConfigurer的init方法
    private void init() throws Exception {
        Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();

        for (SecurityConfigurer<O, B> configurer : configurers) {
            //具体实现看下面
            configurer.init((B) this);
        }

        for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) {
            configurer.init((B) this);
        }
    }

    //以WebSecurity自己为参数调用SecurityConfigurer的configure方法
    @SuppressWarnings("unchecked")
    private void configure() throws Exception {
        Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();

        for (SecurityConfigurer<O, B> configurer : configurers) {
            //具体实现看下面
            configurer.configure((B) this);
        }
    }
}

我们以默认的WebSecurityConfigurerAdapter类分析这两个方法的内部实现,毕竟我们基本都是对该类进行扩展来对Spring Security进行定制配置。

@Order(100)
public abstract class WebSecurityConfigurerAdapter implements
        WebSecurityConfigurer<WebSecurity> {

    public void init(final WebSecurity web) throws Exception {
        //创建HttpSecurity的实例(该对象后面会详细探讨)
        final HttpSecurity http = getHttp();
        //调用WebSecurity的方法将http传递给它保存,
        //后面WebSecurity会使用http的build()方法来构建Filter,
        //所有真正构建Filter的是这个HttpSecurity 。
        //同时,会通过Lambda表达式创建一个Runnable类型的实例
        //传递给WebSecurity,待创建好Filter实例后,最后回调该方法
        web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {
            //供WebSecurity回调的方法
            FilterSecurityInterceptor securityInterceptor = http
                    .getSharedObject(FilterSecurityInterceptor.class);
            //这里只是简单的给WebSecurity的filterSecurityInterceptor属性赋值
            //在WebSecurity的getPrivilegeEvaluator方法中会用到
            web.securityInterceptor(securityInterceptor);
        });
    }

    //该方法默认什么都没做
    public void configure(WebSecurity web) throws Exception {
    }
}

最后我们看下与上面调用有关的WebSecurity中的方法

public final class WebSecurity extends
        AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements
        SecurityBuilder<Filter>, ApplicationContextAware {

    private final List<SecurityBuilder<? extends SecurityFilterChain>> securityFilterChainBuilders = new ArrayList<>();

    //该方法被WebSecurityConfigurerAdapter的init方法调用【添加进HttpSecurity】
    public WebSecurity addSecurityFilterChainBuilder(
            SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder) {
        this.securityFilterChainBuilders.add(securityFilterChainBuilder);
        return this;
    }

    //该方法在WebSecurityConfigurerAdapter的init方法调用
    public WebSecurity postBuildAction(Runnable postBuildAction) {
        this.postBuildAction = postBuildAction;
        return this;
    }

    //该方法被WebSecurityConfigurerAdapter的init方法调用
    public WebSecurity securityInterceptor(FilterSecurityInterceptor securityInterceptor) {
        this.filterSecurityInterceptor = securityInterceptor;
        return this;
    }

    
    //完成最后的构建操作
    @Override
    protected Filter performBuild() throws Exception {
        int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
        List<SecurityFilterChain> securityFilterChains = new ArrayList<>(
                chainSize);
        for (RequestMatcher ignoredRequest : ignoredRequests) {
            securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
        }
        for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
            //分别执行(HttpSecurity对象)build方法得到SecurityFilterChain
            securityFilterChains.add(securityFilterChainBuilder.build());
        }
        //创建FilterChainProxy ,建立SecurityFilterChain与Servlet容器的桥梁
        FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
        if (httpFirewall != null) {
            filterChainProxy.setFirewall(httpFirewall);
        }
        filterChainProxy.afterPropertiesSet();

        Filter result = filterChainProxy;
        //执行回调
        postBuildAction.run();
        return result;
    }
}

执行流程小结

  1. WebSecurityConfiguration收集所有的SecurityConfigurer(WebSecurityConfigurerAdapter)并将其传递给WebSecurity;
  2. WebSecurityConfiguration中执行WebSecurity的build()方法创建springSecurityFilterChain;
  3. WebSecurity的build()方法中执行各个SecurityConfigurer的init和configure方法完成装配工作,并将装配结果SecurityBuilder<SecurityFilterChain>类型实例添加到WebSecurity的变量securityFilterChainBuilders中;
  4. WebSecurity的build()方法中继续执行securityFilterChainBuilders中的SecurityBuilder类型对象的build()方法完成SecurityFilterChain实例的创建;
  5. WebSecurity的build()方法中继续用所有得到的SecurityFilterChain来创建FilterChainProxy实例并返回;

这里面的SecurityConfigurer类型的对象(默认是WebSecurityConfigurerAdapter)是构建SecurityFilterChain的关键,里面的init和configure方法更是完成装配的主要过程,在后面将会对WebSecurityConfigurerAdapter进行深入的分析。

相关文章

网友评论

      本文标题:Spring Security解析三:SecurityFilte

      本文链接:https://www.haomeiwen.com/subject/timhdhtx.html