Spring Security 实现原理 ① 初始化过程

前言

在了解Spring Security初始化过程,可以先了解一下spring bean的生命周期,以及springboot的自动装配原理。

Spring Security的初始化过程是一个复杂但有序的过程,它主要依赖于Spring框架的自动配置机制以及开发者提供的配置信息。以下是从注解方式(Java Configuration)的角度来概述Spring Security在Spring Boot项目中的初始化过程

1. 自动配置类

在Spring Boot项目中,Spring Security的初始化通常是通过自动配置类(Auto-configuration classes)来实现的。这些自动配置类会根据项目中的依赖和配置来决定是否启用以及如何配置Spring Security。主要涉及的自动配置类包括SecurityAutoConfiguration(在springboot的自动装配包的imports文件可以找到)、SpringBootWebSecurityConfiguration等。

在这里插入图片描述

SecurityAutoConfiguration

通过代码可以看到,该类引入了SpringBootWebSecurityConfiguration

@AutoConfiguration(before = UserDetailsServiceAutoConfiguration.class)
@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
@EnableConfigurationProperties(SecurityProperties.class)
@Import({ SpringBootWebSecurityConfiguration.class, SecurityDataConfiguration.class })
public class SecurityAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean(AuthenticationEventPublisher.class)
	public DefaultAuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher publisher) {
		return new DefaultAuthenticationEventPublisher(publisher);
	}

}

SpringBootWebSecurityConfiguration

	/**
	 * Adds the {@link EnableWebSecurity @EnableWebSecurity} annotation if Spring Security
	 * is on the classpath. This will make sure that the annotation is present with
	 * default security auto-configuration and also if the user adds custom security and
	 * forgets to add the annotation. If {@link EnableWebSecurity @EnableWebSecurity} has
	 * already been added or if a bean with name
	 * {@value BeanIds#SPRING_SECURITY_FILTER_CHAIN} has been configured by the user, this
	 * will back-off.
	 */
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN)
	@ConditionalOnClass(EnableWebSecurity.class)
	@EnableWebSecurity
	static class WebSecurityEnablerConfiguration {

	}

@EnableWebSecurity

@EnableWebSecurity表示启用Spring Security。这个注解是初始化Spring Security的入口点,它会触发一系列的自动配置过程。


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import({ WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class,
		HttpSecurityConfiguration.class })
@EnableGlobalAuthentication
public @interface EnableWebSecurity {

	/**
	 * Controls debugging support for Spring Security. Default is false.
	 * @return if true, enables debug support with Spring Security
	 */
	boolean debug() default false;

}

核心在于引入了({ WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class,
HttpSecurityConfiguration.class })

WebSecurityConfiguration

spring security框架有三个核心

  • 整个框架的核心是一个过滤器,这个过滤器名字叫springSecurityFilterChain类型是FilterChainProxy
  • 核心过滤器里面是过滤器链(列表),过滤器链的每个元素都是一组URL对应一组过滤器
  • WebSecurity用来创建FilterChainProxy过滤器,HttpSecurity用来创建过滤器链的每个元素。

而这个三个核心的创建过程,我们也能在WebSecurityConfiguration中看到

在这里插入图片描述

参考:初始化过程

创建WebSecurity
	/**
	 * Sets the {@code <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>}
	 * instances used to create the web configuration.
	 * @param objectPostProcessor the {@link ObjectPostProcessor} used to create a
	 * {@link WebSecurity} instance
	 * @param beanFactory the bean factory to use to retrieve the relevant
	 * {@code <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>} instances used to
	 * create the web configuration
	 * @throws Exception
	 */
	@Autowired(required = false)
	public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,
			ConfigurableListableBeanFactory beanFactory) throws Exception {
		this.webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
		if (this.debugEnabled != null) {
			this.webSecurity.debug(this.debugEnabled);
		}
		List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new AutowiredWebSecurityConfigurersIgnoreParents(
				beanFactory)
			.getWebSecurityConfigurers();
		webSecurityConfigurers.sort(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;
		}
		for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
			this.webSecurity.apply(webSecurityConfigurer);
		}
		this.webSecurityConfigurers = webSecurityConfigurers;
	}
  • 该方法负责收集配置类对象列表webSecurityConfigurers,方法执行时会先得到webSecurityConfigurers并排序(所有实现了WebSecurityConfigurerAdapter的配置类实例)并创建WebSecurity,WebSecurity是通过直接new的方式手动创建,并利用objectPostProcessor的实现AutowireBeanFactoryObjectPostProcessor注入spring 容器进行管理;
    在这里插入图片描述

  • 通过AutowiredWebSecurityConfigurersIgnoreParents的getWebSecurityConfigurers()方法,获取所有实现WebSecurityConfigurer的配置类,并管理在map中
    在这里插入图片描述
    在这里插入图片描述

  • 关于objectPostProcessor,该类可以实现spring bean的手动装配
    参考:objectPostProcessor
    参考2

调用springSecurityFilterChain创建过滤器链

WebSecurity是一个建造者,所以我们去看这些方法build(); doBuild(); init(); configure(); performBuild();
在这里插入图片描述
build()方法定义在WebSecurity对象的父类AbstractSecurityBuilder中,调用的AbstractConfiguredSecurityBuilder#doBuild()
在这里插入图片描述
doBuild()先调用init();configure();等方法
doBuild()最后调用了WebSecurity对象的perfomBuild(),来创建了FilterChainProxy对象,performBuild()里遍历securityFilterChainBuilders建造者列表,把每个SecurityBuilder建造者对象构建成SecurityFilterChain实例,最后创建并返回FilterChainProxy。
在这里插入图片描述
参考:参考1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值