概述 SecurityAutoConfiguration主要负责在项目启动时为当前的web容器添加一些必要的配置类
 
SecurityAutoConfiguration 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Configuration @ConditionalOnClass(DefaultAuthenticationEventPublisher.class) @EnableConfigurationProperties(SecurityProperties.class) @Import({ SpringBootWebSecurityConfiguration.class, WebSecurityEnablerConfiguration.class, 		SecurityDataConfiguration.class }) public  class  SecurityAutoConfiguration  {	@Bean  	@ConditionalOnMissingBean(AuthenticationEventPublisher.class)  	public  DefaultAuthenticationEventPublisher authenticationEventPublisher (ApplicationEventPublisher publisher)  { 		return  new  DefaultAuthenticationEventPublisher (publisher); 	} } 
 
将DefaultAuthenticationEventPublisher注册到spring容器中 
将SecurityProperties注册到spring容器中 
将SpringBootWebSecurityConfiguration、WebSecurityEnablerConfiguration和SecurityDataConfiguration注册到当前容器中 
 
这里我们主要关注一下SpringBootWebSecurityConfiguration、WebSecurityEnablerConfiguration这两个配置类
SpringBootWebSecurityConfiguration 1 2 3 4 5 6 7 8 9 10 11 12 13 @Configuration @ConditionalOnClass(WebSecurityConfigurerAdapter.class) @ConditionalOnMissingBean(WebSecurityConfigurerAdapter.class) @ConditionalOnWebApplication(type = Type.SERVLET) public  class  SpringBootWebSecurityConfiguration  {	@Configuration  	@Order(SecurityProperties.BASIC_AUTH_ORDER)  	static  class  DefaultConfigurerAdapter  extends  WebSecurityConfigurerAdapter  { 	} } 
 
判断类路径下是否有WebSecurityConfigurerAdapter,正常情况是肯定有的,满足条件  
判断spring容器中是否有WebSecurityConfigurerAdapter实例,由于我们没有自己编写自己的类继承它,所以容器中是没有改实例的,满足条件  
判断当前web应用是不是基于servlet的,springmvc就是基于servlet的,满足条件  
 
综上,满足所有条件,将SpringBootWebSecurityConfiguration和DefaultConfigurerAdapter注册到spring容器中
WebSecurityEnablerConfiguration 1 2 3 4 5 6 7 8 @Configuration @ConditionalOnBean(WebSecurityConfigurerAdapter.class) @ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @EnableWebSecurity public  class  WebSecurityEnablerConfiguration  {} 
 
判断spring容器中是否有WebSecurityConfigurerAdapter实例,在上一步的SpringBootWebSecurityConfiguration配置中,最终将WebSecurityConfigurerAdapter的实例DefaultConfigurerAdapter注册到了spring容器中,满足条件  
判断spring容器中是否没有bean的名称为springSecurityFilterChain ,默认我们没有自定义这个bean,满足条件  
判断当前web应用是不是基于servlet的,springmvc就是基于servlet的,满足条件  
 
综上,满足所有条件,将WebSecurityEnablerConfiguration实例注册到spring容器中,并且开启EnableWebSecurity注解,这个EnableWebSecurity注解很重要,下面我们来着重分析一下它
EnableWebSecurity 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) @Target(value = { java.lang.annotation.ElementType.TYPE }) @Documented @Import({ WebSecurityConfiguration.class, 		SpringWebMvcImportSelector.class, 		OAuth2ImportSelector.class }) @EnableGlobalAuthentication @Configuration public  @interface  EnableWebSecurity {	 	boolean  debug ()  default  false ; } 
 
将WebSecurityConfiguration、SpringWebMvcImportSelector和OAuth2ImportSelector注册到spring容器中 
开启EnableGlobalAuthentication注解 
 
接下来我们分析一下WebSecurityConfiguration这个配置类为我们配置了哪些类
WebSecurityConfiguration 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 @Configuration public  class  WebSecurityConfiguration  implements  ImportAware , BeanClassLoaderAware {	private  WebSecurity webSecurity; 	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 (); 	} 	      	@Bean  	@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)  	public  SecurityExpressionHandler<FilterInvocation> webSecurityExpressionHandler ()  { 		return  webSecurity.getExpressionHandler(); 	} 	 	@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(); 	}    	@Bean  	@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)  	public  WebInvocationPrivilegeEvaluator privilegeEvaluator ()  throws  Exception { 		return  webSecurity.getPrivilegeEvaluator(); 	} 	 	@Autowired(required = false)  	public  void  setFilterChainProxySecurityConfigurer (  			ObjectPostProcessor<Object> objectPostProcessor,         	// 注入autowiredWebSecurityConfigurersIgnoreParents这个bean的getWebSecurityConfigurers返回的值 			@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; 	}      	                	@Bean  	public  static  AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents (  			ConfigurableListableBeanFactory beanFactory)  {		return  new  AutowiredWebSecurityConfigurersIgnoreParents (beanFactory); 	} 	 	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; 		} 	} 	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; 	} } 
 
从ConfigurableListableBeanFactory中找到所有SecurityConfigurer<Filter, WebSecurity>,然后初始化webSecurity,在对所有SecurityConfigurer进行排序 
在springSecurityFilterChain实例注册到spring容器中后,将WebInvocationPrivilegeEvaluator、SecurityExpressionHandler、DelegatingApplicationListener等实例注册到spring容器中 
 
EnableGlobalAuthentication 1 2 3 4 5 6 7 8 @Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) @Target(value = { java.lang.annotation.ElementType.TYPE }) @Documented @Import(AuthenticationConfiguration.class) @Configuration public  @interface  EnableGlobalAuthentication {} 
 
@EnableWebSecurity被EnableGlobalAuthentication注解了,从EnableGlobalAuthentication注解我们可以看到它的作用是将AuthenticationConfiguration注册到spring容器中
AuthenticationConfiguration 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 @Configuration @Import(ObjectPostProcessorConfiguration.class) public  class  AuthenticationConfiguration  {	private  AtomicBoolean  buildingAuthenticationManager  =  new  AtomicBoolean (); 	private  ApplicationContext applicationContext; 	private  AuthenticationManager authenticationManager; 	private  boolean  authenticationManagerInitialized; 	private  List<GlobalAuthenticationConfigurerAdapter> globalAuthConfigurers = Collections 			.emptyList(); 	 	private  ObjectPostProcessor<Object> objectPostProcessor; 	      	@Bean  	public  AuthenticationManagerBuilder authenticationManagerBuilder (  			ObjectPostProcessor<Object> objectPostProcessor, ApplicationContext context)  {		         		LazyPasswordEncoder  defaultPasswordEncoder  =  new  LazyPasswordEncoder (context);                   		AuthenticationEventPublisher  authenticationEventPublisher  =  getBeanOrNull(context, AuthenticationEventPublisher.class); 		 		DefaultPasswordEncoderAuthenticationManagerBuilder  result  =  new  DefaultPasswordEncoderAuthenticationManagerBuilder (objectPostProcessor, defaultPasswordEncoder); 		if  (authenticationEventPublisher != null ) {              			result.authenticationEventPublisher(authenticationEventPublisher); 		} 		return  result; 	} 	           	@Bean  	public  static  GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer (  			ApplicationContext context)  {		return  new  EnableGlobalAuthenticationAutowiredConfigurer (context); 	} 	 	@Bean  	public  static  InitializeUserDetailsBeanManagerConfigurer initializeUserDetailsBeanManagerConfigurer (ApplicationContext context)  { 		return  new  InitializeUserDetailsBeanManagerConfigurer (context); 	} 	      	@Bean  	public  static  InitializeAuthenticationProviderBeanManagerConfigurer initializeAuthenticationProviderBeanManagerConfigurer (ApplicationContext context)  { 		return  new  InitializeAuthenticationProviderBeanManagerConfigurer (context); 	} 	public  AuthenticationManager getAuthenticationManager ()  throws  Exception { 		if  (this .authenticationManagerInitialized) { 			return  this .authenticationManager; 		} 		AuthenticationManagerBuilder  authBuilder  =  authenticationManagerBuilder( 				this .objectPostProcessor, this .applicationContext); 		if  (this .buildingAuthenticationManager.getAndSet(true )) { 			return  new  AuthenticationManagerDelegator (authBuilder); 		} 		for  (GlobalAuthenticationConfigurerAdapter config : globalAuthConfigurers) { 			authBuilder.apply(config); 		} 		authenticationManager = authBuilder.build(); 		if  (authenticationManager == null ) { 			authenticationManager = getAuthenticationManagerBean(); 		} 		this .authenticationManagerInitialized = true ; 		return  authenticationManager; 	} 	@Autowired(required = false)  	public  void  setGlobalAuthenticationConfigurers (  			List<GlobalAuthenticationConfigurerAdapter> configurers)  throws  Exception {		Collections.sort(configurers, AnnotationAwareOrderComparator.INSTANCE); 		this .globalAuthConfigurers = configurers; 	} 	@Autowired  	public  void  setApplicationContext (ApplicationContext applicationContext)  { 		this .applicationContext = applicationContext; 	} 	@Autowired  	public  void  setObjectPostProcessor (ObjectPostProcessor<Object> objectPostProcessor)  { 		this .objectPostProcessor = objectPostProcessor; 	} 	@SuppressWarnings("unchecked")  	private  <T> T lazyBean (Class<T> interfaceName)  { 		LazyInitTargetSource  lazyTargetSource  =  new  LazyInitTargetSource (); 		String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( 				applicationContext, interfaceName); 		if  (beanNamesForType.length == 0 ) { 			return  null ; 		} 		Assert.isTrue(beanNamesForType.length == 1 , 				() -> "Expecting to only find a single bean for type "  + interfaceName 						+ ", but found "  + Arrays.asList(beanNamesForType)); 		lazyTargetSource.setTargetBeanName(beanNamesForType[0 ]); 		lazyTargetSource.setBeanFactory(applicationContext); 		ProxyFactoryBean  proxyFactory  =  new  ProxyFactoryBean (); 		proxyFactory = objectPostProcessor.postProcess(proxyFactory); 		proxyFactory.setTargetSource(lazyTargetSource); 		return  (T) proxyFactory.getObject(); 	} 	private  AuthenticationManager getAuthenticationManagerBean ()  { 		return  lazyBean(AuthenticationManager.class); 	} 	private  static  <T> T getBeanOrNull (ApplicationContext applicationContext, Class<T> type)  { 		try  { 			return  applicationContext.getBean(type); 		} catch (NoSuchBeanDefinitionException notFound) { 			return  null ; 		} 	} 	private  static  class  EnableGlobalAuthenticationAutowiredConfigurer  extends  			GlobalAuthenticationConfigurerAdapter  { 		private  final  ApplicationContext context; 		private  static  final  Log  logger  =  LogFactory 				.getLog(EnableGlobalAuthenticationAutowiredConfigurer.class); 		public  EnableGlobalAuthenticationAutowiredConfigurer (ApplicationContext context)  { 			this .context = context; 		} 		@Override  		public  void  init (AuthenticationManagerBuilder auth)  { 			Map<String, Object> beansWithAnnotation = context 					.getBeansWithAnnotation(EnableGlobalAuthentication.class); 			if  (logger.isDebugEnabled()) { 				logger.debug("Eagerly initializing "  + beansWithAnnotation); 			} 		} 	} 	 	static  final  class  AuthenticationManagerDelegator  implements  AuthenticationManager  { 		private  AuthenticationManagerBuilder delegateBuilder; 		private  AuthenticationManager delegate; 		private  final  Object  delegateMonitor  =  new  Object (); 		AuthenticationManagerDelegator(AuthenticationManagerBuilder delegateBuilder) { 			Assert.notNull(delegateBuilder, "delegateBuilder cannot be null" ); 			this .delegateBuilder = delegateBuilder; 		} 		@Override  		public  Authentication authenticate (Authentication authentication)  				throws  AuthenticationException { 			if  (this .delegate != null ) { 				return  this .delegate.authenticate(authentication); 			} 			synchronized  (this .delegateMonitor) { 				if  (this .delegate == null ) { 					this .delegate = this .delegateBuilder.getObject(); 					this .delegateBuilder = null ; 				} 			} 			return  this .delegate.authenticate(authentication); 		} 		@Override  		public  String toString ()  { 			return  "AuthenticationManagerDelegator [delegate="  + this .delegate + "]" ; 		} 	} 	static  class  DefaultPasswordEncoderAuthenticationManagerBuilder  extends  AuthenticationManagerBuilder  { 		private  PasswordEncoder defaultPasswordEncoder; 		 		DefaultPasswordEncoderAuthenticationManagerBuilder( 			ObjectPostProcessor<Object> objectPostProcessor, PasswordEncoder defaultPasswordEncoder) { 			super (objectPostProcessor); 			this .defaultPasswordEncoder = defaultPasswordEncoder; 		} 		@Override  		public  InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication ()  			throws  Exception { 			return  super .inMemoryAuthentication() 				.passwordEncoder(this .defaultPasswordEncoder); 		} 		@Override  		public  JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcAuthentication ()  			throws  Exception { 			return  super .jdbcAuthentication() 				.passwordEncoder(this .defaultPasswordEncoder); 		} 		@Override  		public  <T extends  UserDetailsService > DaoAuthenticationConfigurer<AuthenticationManagerBuilder, T> userDetailsService (  			T userDetailsService)  throws  Exception {			return  super .userDetailsService(userDetailsService) 				.passwordEncoder(this .defaultPasswordEncoder); 		} 	} 	static  class  LazyPasswordEncoder  implements  PasswordEncoder  { 		private  ApplicationContext applicationContext; 		private  PasswordEncoder passwordEncoder; 		LazyPasswordEncoder(ApplicationContext applicationContext) { 			this .applicationContext = applicationContext; 		} 		@Override  		public  String encode (CharSequence rawPassword)  { 			return  getPasswordEncoder().encode(rawPassword); 		} 		@Override  		public  boolean  matches (CharSequence rawPassword,  			String encodedPassword)  {			return  getPasswordEncoder().matches(rawPassword, encodedPassword); 		} 		@Override  		public  boolean  upgradeEncoding (String encodedPassword)  { 			return  getPasswordEncoder().upgradeEncoding(encodedPassword); 		} 		private  PasswordEncoder getPasswordEncoder ()  { 			if  (this .passwordEncoder != null ) { 				return  this .passwordEncoder; 			} 			PasswordEncoder  passwordEncoder  =  getBeanOrNull(this .applicationContext, PasswordEncoder.class); 			if  (passwordEncoder == null ) { 				passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); 			} 			this .passwordEncoder = passwordEncoder; 			return  passwordEncoder; 		} 		@Override  		public  String toString ()  { 			return  getPasswordEncoder().toString(); 		} 	} } 
 
配置了AuthenticationManagerBuilder、InitializeUserDetailsBeanManagerConfigurer、InitializeAuthenticationProviderBeanManagerConfigurer这些必要的配置类,同时也通过@Import(ObjectPostProcessorConfiguration.class)将ObjectPostProcessor注入到spring容器中了
ObjectPostProcessorConfiguration 1 2 3 4 5 6 7 8 9 10 @Configuration public  class  ObjectPostProcessorConfiguration  {	@Bean  	public  ObjectPostProcessor<Object> objectPostProcessor (  			AutowireCapableBeanFactory beanFactory)  {		return  new  AutowireBeanFactoryObjectPostProcessor (beanFactory); 	} } 
 
默认的ObjectPostProcessor就是AutowireBeanFactoryObjectPostProcessor
总结 
将DefaultAuthenticationEventPublisher注册到spring容器中 
将DefaultConfigurerAdapter注册到spring容器中 
开启@EnableWebSecurity注解,将springSecurityFilterChain,WebSecurity,ObjectPostProcessor,AuthenticationManagerBuilder等配置类注入到spring容器中