SpringSecurity------WebSecurityConfiguration配置类

85 篇文章 0 订阅
26 篇文章 1 订阅

SpringSecurity------WebSecurityConfiguration配置类
一、WebSecurityConfiguration是怎样被加载的
二、WebSecurityConfiguration主要做了什么
三、WebSecurityConfiguration的源码分析
1、属性字段
2、核心方法
内部初始化WebSecurity的setFilterChainProxySecurityConfigurer()方法
内部构建FilterChainProxy的springSecurityFilterChain()方法
3、使用@Autowired注入了一些Bean
4、使用@Bean初始化一些Bean
5、实现的接口方法
6、一个内部类
一、WebSecurityConfiguration是怎样被加载的
通过在配置类上加入@EnableWebSecurity注解来引入WebSecurityConfiguration.class配置类,源码如下:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import({ WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class,
        HttpSecurityConfiguration.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
    boolean debug() default false;
}
1
2
3
4
5
6
7
8
9
10
我们可以看到在注解@EnableWebSecurity上使用@Import()引入了WebSecurityConfiguration.class配置类。

二、WebSecurityConfiguration主要做了什么
简单的说,这个类的作用就是用来创建FilterChainProxy,FilterChainProxy是一个Servlet Filter,他是一组SecurityFilterChain的代理,用于管理这些SecurityFilterChain

首先,FilterChainProxy是SpringSecurity提供的基于Servlet标准的过滤器,他可以被Servlet容器使用。SecurityFilterChain是SpringSecurity提供的自有安全过滤器链,他不是基于Servlet标准的过滤器。SpringSecurity使用FilterChainProxy管理一组SecurityFilterChain,这样就可以通过代理的方式将SpringSecurity自有的滤器链应用于Servlet容器。

然后,当前配置类会加载容器中所有的WebSecurityConfigurer配置类、WebSecurityCustomizer配置类(5.4以后)、SecurityFilterChain过滤器链。这些都是用于配置生成一个WebSecurity。

接着,当WebSecurity实例被构建完成后,会使用WebSecurity去创建一个FilterChainProxy,这个FilterChainProxy会被放到容器中。

三、WebSecurityConfiguration的源码分析
1、属性字段
//SpringSecurity的FilterChainProxy的建造器
private WebSecurity webSecurity;
//标识是否开启debug模式,来自注解@EnableWebSecurity的属性debug
private Boolean debugEnabled;
//SpringSecurity的配置类列表
private List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers;
//SpringSecurity的核心过滤器链的列表
private List<SecurityFilterChain> securityFilterChains = Collections.emptyList();
//用户自定义WebSecurity的配置类列表(5.4版本之后新增的配置类)
private List<WebSecurityCustomizer> webSecurityCustomizers = Collections.emptyList();
//一个类加载器
private ClassLoader beanClassLoader;
//对象后处理器(这里依赖注入的是AutowireBeanFactoryObjectPostProcessor)
@Autowired(required = false)
private ObjectPostProcessor<Object> objectObjectPostProcessor;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2、核心方法
内部初始化WebSecurity的setFilterChainProxySecurityConfigurer()方法
在这个方法中会创建一个WebSecurity实例,然后将注解参数列表中@Value()注解引入的所有WebSecurityConfigurer配置设置到WebSecurity实例中。同时初始化了当前配置类的两个属性值webSecurity和webSecurityConfigurers。

@Value()引入方式就是AutowiredWebSecurityConfigurersIgnoreParents的方法调用。

/**
* 获取并设置容器中已经加载的所有WebSecurityConfigurer实例用于配置,初始化一个WebSecurity

* @param objectPostProcessor   后处理对象(AutowireBeanFactoryObjectPostProcessor)
* @param webSecurityConfigurers 用户自定义的配置(WebSecurityConfigurerAdapter的子类或是WebSecurityConfigurer接口的实现)
* @throws Exception
*/
@Autowired(required = false)
public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,
        @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") 
        List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
        throws Exception {
    /**
     * 1、初始化一个WebSecurity实例,并其赋值到类属性webSecurity上
     */
    this.webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
    /**
     * 2、设置是否开启debug模式
     */
    if (this.debugEnabled != null) {
        this.webSecurity.debug(this.debugEnabled);
    }
    /**
     * 3、根据@Order注解排序,然后检测配置排序是否有重复
     */
    webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);
    Integer previousOrder = null;
    Object previousConfig = null;
    for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {
        //AnnotationAwareOrderComparator是本类中的一个内部类,下面有介绍
        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;
    }
    /**
    * 4、将配置添加到webSecurity中
    */
    for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
        this.webSecurity.apply(webSecurityConfigurer);
    }
    /**
    * 5、将配置类列表复制到类属性webSecurityConfigurers上
    */
    this.webSecurityConfigurers = webSecurityConfigurers;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
内部构建FilterChainProxy的springSecurityFilterChain()方法
首先,在这个方法中首先会判断是否有用户自定义的WebSecurityConfigurer和SecurityFilterChain:

如果这两种自定义实例同时存在则会抛出异常。
如果只存在SecurityFilterChains,将其设置到已经被创建的webSecurity中。
如果这两个自定义实例都不存在,则会创建一个默认的WebSecurityConfigurerAdapter配置,并将其设置到已经被创建的webSecurity中。
然后,调用webSecurity.build()方法创建一个FilterChainProxy,这个Bean会被放到容器中

/**
 * 创建FilterChainProxy代理
 * 
 * @return
 * @throws Exception
 */
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
    /**
     * 1、判断是否有自定义配置类
     */
    boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty();
    /**
     * 2、判断是否有自定义配置的SecurityFilterChain
     */
    boolean hasFilterChain = !this.securityFilterChains.isEmpty();
    /**
     * 3、自定义的WebSecurityConfigurerAdapter和SecurityFilterChain不能同时存在
     */
    Assert.state(!(hasConfigurers && hasFilterChain),
            "Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one.");
    /**
     * 4、如果没有配置类且没有SecurityFilterChain,创建一个默认配置,并添加到webSecurity
     */
    if (!hasConfigurers && !hasFilterChain) {
        WebSecurityConfigurerAdapter adapter = this.objectObjectPostProcessor
                .postProcess(new WebSecurityConfigurerAdapter() {
            });
        this.webSecurity.apply(adapter);
    }
    /**
     * 5、设置webSecurity的拦截器链和拦截器
     */
    for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {
        this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);
        for (Filter filter : securityFilterChain.getFilters()) {
            if (filter instanceof FilterSecurityInterceptor) {
                this.webSecurity.securityInterceptor((FilterSecurityInterceptor) filter);
                break;
            }
        }
    }
    /**
     * 6、用户的一些自定义配置webSecurity
     */
    for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
        customizer.customize(this.webSecurity);
    }
    /**
     * 7、以上配置完成webSecurity后调用WebSecurity.build()方法创建FilterChainProxy
     */
    return this.webSecurity.build();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
FilterChainProxy的创建过程

3、使用@Autowired注入了一些Bean
注入容器中所有用户自定义的WebSecurityCustomizer

/**
* 注入容器中所有用户自定义的WebSecurityCustomizer,用于自定义WebSecurity

* @param webSecurityCustomizers
*/
@Autowired(required = false)
void setWebSecurityCustomizers(List<WebSecurityCustomizer> webSecurityCustomizers) {
    webSecurityCustomizers.sort(AnnotationAwareOrderComparator.INSTANCE);
    this.webSecurityCustomizers = webSecurityCustomizers;
}
1
2
3
4
5
6
7
8
9
10
注入容器中所有的SecurityFilterChain

/**
* 依赖注入所有的SecurityFilterChain

* @param securityFilterChains
*/
@Autowired(required = false)
void setFilterChains(List<SecurityFilterChain> securityFilterChains) {
    securityFilterChains.sort(AnnotationAwareOrderComparator.INSTANCE);
    this.securityFilterChains = securityFilterChains;
}
1
2
3
4
5
6
7
8
9
10
4、使用@Bean初始化一些Bean
/**
 * 初始化一个AutowiredWebSecurityConfigurersIgnoreParents实例,用于加载容器中的所有WebSecurityConfigurer实例
 * 
 * @param beanFactory
 * @return
 */
@Bean
public static AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
        ConfigurableListableBeanFactory beanFactory) {
     return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
}
1
2
3
4
5
6
7
8
9
10
11
/**
 * 一个事件监听器的管理器,用于管理所有的鉴权事件
 * 
 * @return
 */
@Bean
public static DelegatingApplicationListener delegatingApplicationListener() {
    return new DelegatingApplicationListener();
}
1
2
3
4
5
6
7
8
9
/**
 * 权限表达式的支持
 * 
 * @return
 */
@Bean
@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public SecurityExpressionHandler<FilterInvocation> webSecurityExpressionHandler() {
    return this.webSecurity.getExpressionHandler();
}
1
2
3
4
5
6
7
8
9
10
/**
 * 权限评估器。对于JSP-tag支持是必须的
 * 
 * @return
 */
@Bean
@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public WebInvocationPrivilegeEvaluator privilegeEvaluator() {
    return this.webSecurity.getPrivilegeEvaluator();
}
1
2
3
4
5
6
7
8
9
10
/**
 * 钩子接口,用于修改BeanFactory
 * 
 * @return
 */
@Bean
public static BeanFactoryPostProcessor conversionServicePostProcessor() {
    return new RsaKeyConversionServicePostProcessor();
}
1
2
3
4
5
6
7
8
9
5、实现的接口方法
这个方法是接口ImportAware的方法,当前配置类是通过@EnableWebSecurity注解上的@Import注解引入的,实现该接口的方法使得当前配置类可以获取到@EnableWebSecurity的debug属性值

/**
 * 获取注解的日志级别并设置(ImportAware接口的方法)
 */
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
    Map<String, Object> enableWebSecurityAttrMap = importMetadata
            .getAnnotationAttributes(EnableWebSecurity.class.getName());
    AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes.fromMap(enableWebSecurityAttrMap);
    this.debugEnabled = enableWebSecurityAttrs.getBoolean("debug");
    if (this.webSecurity != null) {
        this.webSecurity.debug(this.debugEnabled);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
这个接口可以使得当前配置类获取到加载他的类加载器

/**
 * 设置类加载器(BeanClassLoaderAware接口的方法)
 */
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
    this.beanClassLoader = classLoader;
}
1
2
3
4
5
6
7
6、一个内部类
用于获取类上的@Order注解,并提供比较的功能

/**
 * 获取类上的Order注解的值
 * 
 * @author dongyaowei
 * @date 2020年12月22日
 */
private static class AnnotationAwareOrderComparator extends OrderComparator {
    private static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
    @Override
    protected int getOrder(Object obj) {
        return lookupOrder(obj);
    }
    private static int lookupOrder(Object obj) {
        if (obj instanceof Ordered) {
            return ((Ordered) obj).getOrder();
        }
        if (obj != null) {
            Class<?> clazz = ((obj instanceof Class) ? (Class<?>) obj : obj.getClass());
            Order order = AnnotationUtils.findAnnotation(clazz, Order.class);
            if (order != null) {
                return order.value();
            }
        }
        return Ordered.LOWEST_PRECEDENCE;
    }
}
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值