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 {
我们可以看到在注解@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;
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;
内部构建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();
}
FilterChainProxy的创建过程
3、使用@Autowired注入了一些Bean
注入容器中所有用户自定义的WebSecurityCustomizer
/**
* 注入容器中所有用户自定义的WebSecurityCustomizer,用于自定义WebSecurity
*
* @param webSecurityCustomizers
*/
@Autowired(required = false)
void setWebSecurityCustomizers(List<WebSecurityCustomizer> webSecurityCustomizers) {
webSecurityCustomizers.sort(AnnotationAwareOrderComparator.INSTANCE);
this.webSecurityCustomizers = webSecurityCustomizers;
}
注入容器中所有的SecurityFilterChain
/**
* 依赖注入所有的SecurityFilterChain
*
* @param securityFilterChains
*/
@Autowired(required = false)
void setFilterChains(List<SecurityFilterChain> securityFilterChains) {
securityFilterChains.sort(AnnotationAwareOrderComparator.INSTANCE);
this.securityFilterChains = securityFilterChains;
}
4、使用@Bean初始化一些Bean
/**
* 初始化一个AutowiredWebSecurityConfigurersIgnoreParents实例,用于加载容器中的所有WebSecurityConfigurer实例
*
* @param beanFactory
* @return
*/
@Bean
public static AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
ConfigurableListableBeanFactory beanFactory) {
return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
/**
* 一个事件监听器的管理器,用于管理所有的鉴权事件
*
* @return
*/
@Bean
public static DelegatingApplicationListener delegatingApplicationListener() {
return new DelegatingApplicationListener();
/**
* 权限表达式的支持
*
* @return
*/
@Bean
@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public SecurityExpressionHandler<FilterInvocation> webSecurityExpressionHandler() {
return this.webSecurity.getExpressionHandler();
/**
* 权限评估器。对于JSP-tag支持是必须的
*
* @return
*/
@Bean
@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public WebInvocationPrivilegeEvaluator privilegeEvaluator() {
return this.webSecurity.getPrivilegeEvaluator();
}
/**
* 钩子接口,用于修改BeanFactory
*
* @return
*/
@Bean
public static BeanFactoryPostProcessor conversionServicePostProcessor() {
return new RsaKeyConversionServicePostProcessor();
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);
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;
}
}