SpringSecuirty源码学习(四)

本文深入探讨SpringSecurity的构建过程,从用户自定义配置类开始,通过@EnableWebSecurity注解,到WebSecurityConfiguration的创建和构建。重点解析AbstractConfiguredSecurityBuilder的模板方法、WebSecurityConfigurerAdapter的init()和configurer(),以及WebSecurity的performBuild()步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

总结创建WebSecuirty的创建过程,及其构建过程。有和前面重复的地方,不管了…

1. 用户自定义的配置类

@EnableWebSecurity
@ComponentScan("fn.wd.security")
public class SpringSecurityConfiger extends WebSecurityConfigurerAdapter {
    ...
}

2. @EnableWebSecurity

@Import({ WebSecurityConfiguration.class, ObjectPostProcessorConfiguration.class,
        SpringWebMvcImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
    ...
}

3. WebSecurityConfiguration中创建WebSecurity

    @Autowired(required = false)
    public void setFilterChainProxySecurityConfigurer(
            //参数一:注入被@EnableWebSecurity注入导入的后置处理器
            ObjectPostProcessor<Object> objectPostProcessor,
            //参数二:注入spring web容器中所有的WebSecurityConfigurer
    List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers) {
        //1.创建WebSecurity,传递objectPostProcessor,是为了当这个构建器构建对象完成后,可以给这个对象进行后置处理
        //2.后置处理WebSecurity
        //3.PS:后置处理的功能是:使容器外的对象享受像spring容器内的bean一样的待遇
        webSecurity = objectPostProcessor
                .postProcess(new WebSecurity(objectPostProcessor));
        if (debugEnabled != null) {
            webSecurity.debug(debugEnabled);
        }

        //将配置WebSecurity的配置器排序,这里通常就是我们自定义的那个SecurityConfigurerAdapter
        Collections.sort(webSecurityConfigurers, AnnotationAwareOrderComparator.INSTANCE);

        //如果有多个配置器,配置顺序不能是一样的,否则通不过
        Integer previousOrder = null;
        Object previousConfig = null;
        for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {
            Integer order = AnnotationAwareOrderComparator.lookupOrder(config);
            if (previousOrder != null && previousOrder.equals(order)) {
                throw new IllegalStateException(
                        "@Order on WebSecurityConfigurers must be unique. Order of "
                                + order + " was already used on " + previousConfig + ", so it cannot be used on "
                                + config + " too.");
            }
            previousOrder = order;
            previousConfig = config;
        }
        //让我们自定义的SecurityConfigurerAdapter,应用到new出来的这个WebSecurity
        for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
            webSecurity.apply(webSecurityConfigurer);
        }
        //将用到的配置器放到属性中,以提示:已经对WebSecurity进行配置了
        this.webSecurityConfigurers = webSecurityConfigurers;
    }

可以看到,webSecurityConfigurers中就是我们自定义的那一个:


这里写图片描述

4. WebSecurityConfiguration中触发WebSecurity的构建过程

    //构建的bean的名字叫做:springSecurityFilterChain
    @Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
    public Filter springSecurityFilterChain() throws Exception {
        //看webSecurityConfigurers是不是空,以判断是否对WebSecurity进行了配置
        boolean hasConfigurers = webSecurityConfigurers != null
                && !webSecurityConfigurers.isEmpty();

        //如果没有配置(即:用户没有自定义WebSecurityConfigurerAdapter),那么框架会给一个空实现,所有配置功能都使用WebSecurityConfigurerAdapter中默认的
        if (!hasConfigurers) {
            WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
                    .postProcess(new WebSecurityConfigurerAdapter() {
                    });
            webSecurity.apply(adapter);
        }

        //触发FilterChainProxy的构建过程
        return webSecurity.build();
    }

5.AbstractConfiguredSecurityBuilder定义构建模版


这里写图片描述

AbstractConfiguredSecurityBuilder是WebSecurity的父类,定义了doBuild()方法的执行模版。

    //build()->doBuild();做了些什么呢?前文有提到过哦~
    protected final O doBuild() throws Exception {
        //针对WebSecurity.这里的configurers指的就是我们自定义的那个WebSecurityConfigurer
        synchronized (configurers) {
            buildState = BuildState.INITIALIZING;

            beforeInit();
            //init()前面也说过,迭代所有的configurer,调用它们的init(builder)
            init();

            buildState = BuildState.CONFIGURING;

            beforeConfigure();
            //configure()前面也说过,迭代所有的configurer,调用它们的configure(builder)
            configure();

            buildState = BuildState.BUILDING;

            //performBuild()需要子类实现,WebSecurity中是怎么实现的呢?
            O result = performBuild();

            buildState = BuildState.BUILT;

            return result;
        }
    }

WebSecurityConfigurerAdapter完成模版方法中的init()

这里触发了HttpSecurity的创建(后面详细讨论),并将其设置到WebSecurity中。

    public void init(final WebSecurity web) throws Exception {
        final HttpSecurity http = getHttp();
        //将HttpSecurity添加到WebSecurity的securityFilterChainBuilders属性中
        web.addSecurityFilterChainBuilder(http).postBuildAction(new Runnable() {
            public void run() {
                FilterSecurityInterceptor securityInterceptor = http
                        .getSharedObject(FilterSecurityInterceptor.class);
                web.securityInterceptor(securityInterceptor);
            }
        });
    }

SpringSecurityConfiger完成模版方法中的configurer()

注意:这个类并不是框架的,是需要用户自定义实现的。WebSecurityConfigurerAdapter中configurer()是空实现的,由子类(用户自定义的)去完成实现。一个例子:

@EnableWebSecurity
@ComponentScan("fn.wd.security")
public class SpringSecurityConfiger extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(WebSecurity web) throws Exception {
        /*
         *  web.ignoring()返回的是ignoredRequestRegistry,最终将忽略的请求
         * 添加到WebSecurity中的ignoredRequests属性中。
         */
        web.ignoring().antMatchers("/static/**");
        web.ignoring().antMatchers("/favicon.ico");
        web.ignoring().antMatchers("/resources/**");
    }
}

它的功能还记得吗?前文有提到哦~~

WebSecurity完成模版方法中的performBuild()

有关异常和校验等的代码被我删掉了,只保留了核心的,请自行查看源码。

@Override
    protected Filter performBuild() throws Exception {
        //ignoredRequests.size():是获取忽略的请求个数
        //securityFilterChainBuilders.size():是获取“过滤器链的配置器”的个数
        int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();

        //链,集合
        List<SecurityFilterChain> securityFilterChains 
                    = new ArrayList<SecurityFilterChain>(chainSize);
        //给需要忽略的请求分别创建没有一个过滤器的链
        for (RequestMatcher ignoredRequest : ignoredRequests) {
            securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
        }
        //使用“过滤器链的配置器”创建过滤器链
        for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
            //触发了HttpSecurity的构建过程(后面详细讨论)
            securityFilterChains.add(securityFilterChainBuilder.build());
        }

        //创建过滤器链的代理,将所有的过滤器链都封装进去
        FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);

        if (httpFirewall != null) {
            filterChainProxy.setFirewall(httpFirewall);
        }
        filterChainProxy.afterPropertiesSet();

        Filter result = filterChainProxy;

        postBuildAction.run();

        //返回这个过滤器链的代理
        return result;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值