spring security启动流程解析(一)SecurityAutoConfiguration

在springboot体系下我们一般是找 xxxAutoConfiguration,那么这里我们可以通过查找securityAutoConfiguration可以找到如下类:

  • SecurityAutoConfiguration
  • SecurityFilterAutoConfiguration
  • SecurityRequestMatcherProviderAutoConfiguration
  • ManagementWebSecurityAutoConfiguration
  • MockMvcSecurityAutoConfiguration
  • ReactiveManagementWebSecurityAutoConfiguration
  • ReactiveSecurityAutoConfiguration
    这些类都是在springboot-autoconfig 包下面,即我们一旦引入spring-security的相关包时将初始化加载以上的一些配置。
SecurityAutoConfiguration
@Configuration
//当引入了spring-security-core包时即自动启用该类
@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
//启用配置
@EnableConfigurationProperties(SecurityProperties.class)
//导入以下几个类,我们知道import即加载实例化类到ioc容器
@Import({ SpringBootWebSecurityConfiguration.class, WebSecurityEnablerConfiguration.class,
		SecurityDataConfiguration.class })
public class SecurityAutoConfiguration {
//实例化认证事件发布器
	@Bean
	@ConditionalOnMissingBean(AuthenticationEventPublisher.class)
	public DefaultAuthenticationEventPublisher authenticationEventPublisher(
			ApplicationEventPublisher publisher) {
		return new DefaultAuthenticationEventPublisher(publisher);
	}

}

接着我们来看这三个类

  • SpringBootWebSecurityConfiguration
  • WebSecurityEnablerConfiguration
  • SecurityDataConfiguration
SpringBootWebSecurityConfiguration
@Configuration
@ConditionalOnClass(WebSecurityConfigurerAdapter.class)
@ConditionalOnMissingBean(WebSecurityConfigurerAdapter.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
public class SpringBootWebSecurityConfiguration {
	//配置一个空的 WebSecurityConfigurerAdapter 静态子类实际没做什么操作
	@Configuration
	@Order(SecurityProperties.BASIC_AUTH_ORDER)
	static class DefaultConfigurerAdapter extends WebSecurityConfigurerAdapter {

	}

}
WebSecurityEnablerConfiguration
@Configuration
@ConditionalOnBean(WebSecurityConfigurerAdapter.class)
@ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
//最重要的是这个注解
@EnableWebSecurity
public class WebSecurityEnablerConfiguration {

}

我们看这个注解@EnableWebSecurity

@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
//这里又导入了三个配置类
@Import({ WebSecurityConfiguration.class,
//这两个类的作用大家如果不了解可以去看ImportSelector相关文章这里不多介绍
		SpringWebMvcImportSelector.class,
		OAuth2ImportSelector.class })
//此处启用了这个配置实际导入了AuthenticationConfiguration此类
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
	//可以给注解配置一个debug属性用于调试
	boolean debug() default false;
}

SecurityDataConfiguration 此类纯粹只是为了整合spring-data模块使用。这里暂不解释

接着我们来看@EableWebSecurity中导入的类

  • WebSecurityConfiguration
  • SpringWebMvcImportSelector
  • OAuth2ImportSelector
  • AuthenticationConfiguration
    上面的系类步骤就为了此处服务,我们先来看一张官方图再来看这个类
    在这里插入图片描述
WebSecurityConfiguration
@Configuration
//此处实现了importAware以及BeanClassLoaderAware两个接口,在springIOC中
//相当于赋予当前类拥有这两个类的能力
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
	private WebSecurity webSecurity;
	//从注解中获得的debug属性
	private Boolean debugEnabled;
	//安全配置容器
	private List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers;
	//由父类接口提供的能力
	private ClassLoader beanClassLoader;
	
	@Autowired(required = false)
	private ObjectPostProcessor<Object> objectObjectPostProcessor;
	//实例化一个委托应用监听器
	@Bean
	public static DelegatingApplicationListener delegatingApplicationListener() {
		return new DelegatingApplicationListener();
	}
	//实例化security表达式处理器
	@Bean
	@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
	public SecurityExpressionHandler<FilterInvocation> webSecurityExpressionHandler() {
		return webSecurity.getExpressionHandler();
	}

    // 通过webSecurity build 构造出 Spring Security Filter Chain
	@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
	public Filter springSecurityFilterChain() throws Exception {
		boolean hasConfigurers = webSecurityConfigurers != null
				&& !webSecurityConfigurers.isEmpty();
		if (!hasConfigurers) {
			WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
					.postProcess(new WebSecurityConfigurerAdapter() {
					});
			webSecurity.apply(adapter);
		}
		return webSecurity.build();
	}

	//创建一个web调用评估器
	@Bean
	@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
	public WebInvocationPrivilegeEvaluator privilegeEvaluator() throws Exception {
		return webSecurity.getPrivilegeEvaluator();
	}

	//从springioc容器获取所有的securityConfigure并缓存到当前webSecurityConfigurers容器中备用。
	@Autowired(required = false)
	public void setFilterChainProxySecurityConfigurer(
			ObjectPostProcessor<Object> objectPostProcessor,
			@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
			throws Exception {
		webSecurity = objectPostProcessor
				.postProcess(new WebSecurity(objectPostProcessor));
		if (debugEnabled != null) {
			webSecurity.debug(debugEnabled);
		}

		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;
		}
		for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
			webSecurity.apply(webSecurityConfigurer);
		}
		this.webSecurityConfigurers = webSecurityConfigurers;
	}

	//实例化一个AutowiredWebSecurityConfigurersIgnoreParents对象用于获取所有配置类。
	//上一个方法中注入此示例调用getWebSecurityConfigurers获取到的所有configure。
	//并做了加载排序以及设置属性等操作。
	@Bean
	public static AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
			ConfigurableListableBeanFactory beanFactory) {
		return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
	}

	//获取所有ordered注解用于排序加载
	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;
		}
	}

	
	//用于获取一些源数据,此处用于获取@EnableWebSecurity中的debug属性。
	public void setImportMetadata(AnnotationMetadata importMetadata) {
		Map<String, Object> enableWebSecurityAttrMap = importMetadata
				.getAnnotationAttributes(EnableWebSecurity.class.getName());
		AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes
				.fromMap(enableWebSecurityAttrMap);
		debugEnabled = enableWebSecurityAttrs.getBoolean("debug");
		if (webSecurity != null) {
			webSecurity.debug(debugEnabled);
		}
	}

	//父类功能提供类加载器
	public void setBeanClassLoader(ClassLoader classLoader) {
		this.beanClassLoader = classLoader;
	}
}

篇幅有限仅能介绍完一个接口,后续接口另起篇幅。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值