09 - spring security加载流程
Spring Security 加载流程摘要: 核心配置类HttpSecurityConfiguration通过@Bean创建原型作用域的HttpSecurity对象,初始化默认安全配置(CSRF、登录页等)。 SpringBootWebSecurityConfiguration提供默认的SecurityFilterChain Bean,配置基础认证规则(anyRequest().authenti
spring security加载流程
文档
- 00 - spring security框架使用
- 01 - spring security自定义登录页面
- 02 - spring security基于配置文件及内存的账号密码
- 03 - spring security自定义登出页面
- 04 - spring security关闭csrf攻击防御
- 05 - spring security权限控制
- 06 - spring security角色和权限设置
- 07 - spring security基于数据库的账号密码
- 08 - spring security基于jdbc的账号密码
说明
- spring security版本:3.2.0
spring security加载流程
-
创建
HttpSecurity对象,此处用的是@Scope("prototype")注解,在自定义配置中,操作的就是该对象// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package org.springframework.security.config.annotation.web.configuration; @Configuration( proxyBeanMethods = false ) class HttpSecurityConfiguration { // ... @Bean({"org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity"}) @Scope("prototype") HttpSecurity httpSecurity() throws Exception { LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(this.context); AuthenticationManagerBuilder authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(this.objectPostProcessor, passwordEncoder); authenticationBuilder.parentAuthenticationManager(this.authenticationManager()); authenticationBuilder.authenticationEventPublisher(this.getAuthenticationEventPublisher()); HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, this.createSharedObjects()); WebAsyncManagerIntegrationFilter webAsyncManagerIntegrationFilter = new WebAsyncManagerIntegrationFilter(); webAsyncManagerIntegrationFilter.setSecurityContextHolderStrategy(this.securityContextHolderStrategy); http.csrf(Customizer.withDefaults()).addFilter(webAsyncManagerIntegrationFilter).exceptionHandling(Customizer.withDefaults()).headers(Customizer.withDefaults()).sessionManagement(Customizer.withDefaults()).securityContext(Customizer.withDefaults()).requestCache(Customizer.withDefaults()).anonymous(Customizer.withDefaults()).servletApi(Customizer.withDefaults()).apply(new DefaultLoginPageConfigurer()); http.logout(Customizer.withDefaults()); this.applyCorsIfAvailable(http); this.applyDefaultConfigurers(http); return http; } } -
默认的
SecurityFilterChain对象@Configuration( proxyBeanMethods = false ) @ConditionalOnWebApplication( type = Type.SERVLET ) class SpringBootWebSecurityConfiguration { // ... @Configuration( proxyBeanMethods = false ) @ConditionalOnDefaultWebSecurity static class SecurityFilterChainConfiguration { SecurityFilterChainConfiguration() { } @Bean @Order(2147483642) SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests((requests) -> { ((AuthorizeHttpRequestsConfigurer.AuthorizedUrl)requests.anyRequest()).authenticated(); }); http.formLogin(Customizer.withDefaults()); http.httpBasic(Customizer.withDefaults()); return (SecurityFilterChain)http.build(); } } } -
上面是默认的
SecurityFilterChain类型的Bean,实际使用中,我们会自定义SecurityFilterChain类型的Bean,当我们自定义时,上面的默认配置会失效 -
定义
SecurityFilterChain类型的Bean时,会注入HttpSecurity对象,就是在最开始的流程中创建的,在调用HttpSecurity以下方法时,会创建更多其它相关的对象http.formLogin(Customizer.withDefaults());,1️⃣http.build(),6️⃣
-
接口:
SecurityBuilder-
实现类:
AbstractSecurityBuilder-
方法:
public final O build() throws Exception,7️⃣public final O build() throws Exception { if (this.building.compareAndSet(false, true)) { this.object = this.doBuild(); return this.object; } else { throw new AlreadyBuiltException("This object has already been built"); } } -
子类:
AbstractConfiguredSecurityBuilder-
属性:
private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers; -
方法:
protected final O doBuild() throws Exception,8️⃣protected final O doBuild() throws Exception { synchronized(this.configurers) { this.buildState = AbstractConfiguredSecurityBuilder.BuildState.INITIALIZING; this.beforeInit(); this.init(); this.buildState = AbstractConfiguredSecurityBuilder.BuildState.CONFIGURING; this.beforeConfigure(); this.configure(); this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILDING; O result = this.performBuild(); this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILT; return result; } }说明:
- 关注
this.beforeConfigure();及this.configure();方法
- 关注
-
方法:
private void configure(),🔟private void configure() throws Exception { Collection<SecurityConfigurer<O, B>> configurers = this.getConfigurers(); Iterator var2 = configurers.iterator(); while(var2.hasNext()) { SecurityConfigurer<O, B> configurer = (SecurityConfigurer)var2.next(); configurer.configure(this); } }说明:这里我们关注
FormLoginConfigurer -
子类:
HttpSecurity-
方法:
public HttpSecurity formLogin(Customizer<FormLoginConfigurer<HttpSecurity>> formLoginCustomizer) throws Exception,2️⃣public HttpSecurity formLogin(Customizer<FormLoginConfigurer<HttpSecurity>> formLoginCustomizer) throws Exception { formLoginCustomizer.customize((FormLoginConfigurer)this.getOrApply(new FormLoginConfigurer())); return this; }说明:
- 实际使用中,我们会在自定义
SecurityFilterChain类型的Bean时,注入HttpSecurity对象,并且调用formLogin方法 formLogin方法的入参formLoginCustomizer,一般会以匿名内部类的方式传入,该匿名内部类重写customize方法customize方法的入参为FormLoginConfigurer对象,所以在我们自定义的配置中,实际操作的是FormLoginConfigurer对象,该对象来自于(FormLoginConfigurer)this.getOrApply(new FormLoginConfigurer())(FormLoginConfigurer)this.getOrApply(new FormLoginConfigurer())会向configurers属性中添加一个键值对this.configurers.put(clazz, configs);,configs是List类型,new FormLoginConfigurer()是其中的元素
- 实际使用中,我们会在自定义
-
方法:
protected void beforeConfigure() throws Exception,9️⃣protected void beforeConfigure() throws Exception { if (this.authenticationManager != null) { this.setSharedObject(AuthenticationManager.class, this.authenticationManager); } else { ObservationRegistry registry = this.getObservationRegistry(); AuthenticationManager manager = (AuthenticationManager)this.getAuthenticationRegistry().build(); if (!registry.isNoop() && manager != null) { this.setSharedObject(AuthenticationManager.class, new ObservationAuthenticationManager(registry, manager)); } else { this.setSharedObject(AuthenticationManager.class, manager); } } }说明:此处会向
sharedObjects属性中添加一个键值对this.setSharedObject(AuthenticationManager.class, manager);,该manager为ProviderManager对象
-
-
-
-
-
接口:
SecurityConfigurer-
实现类:
SecurityConfigurerAdapter-
子类:
AbstractHttpConfigurer-
子类:
AbstractAuthenticationFilterConfigurer-
属性:
private F authFilter;说明:
authFilter属性的值是UsernamePasswordAuthenticationFilter对象 -
构造方法,4️⃣
protected AbstractAuthenticationFilterConfigurer(F authenticationFilter, String defaultLoginProcessingUrl) { this(); this.authFilter = authenticationFilter; if (defaultLoginProcessingUrl != null) { this.loginProcessingUrl(defaultLoginProcessingUrl); } }说明:
- 这里的
authenticationFilter是UsernamePasswordAuthenticationFilter对象 - 该
UsernamePasswordAuthenticationFilter对象会加入到FormLoginConfigurer对象的authFilter属性中
- 这里的
-
方法:
public void configure(B http),1️⃣1️⃣public void configure(B http) throws Exception { PortMapper portMapper = (PortMapper)http.getSharedObject(PortMapper.class); if (portMapper != null) { this.authenticationEntryPoint.setPortMapper(portMapper); } RequestCache requestCache = (RequestCache)http.getSharedObject(RequestCache.class); if (requestCache != null) { this.defaultSuccessHandler.setRequestCache(requestCache); } this.authFilter.setAuthenticationManager((AuthenticationManager)http.getSharedObject(AuthenticationManager.class)); this.authFilter.setAuthenticationSuccessHandler(this.successHandler); this.authFilter.setAuthenticationFailureHandler(this.failureHandler); if (this.authenticationDetailsSource != null) { this.authFilter.setAuthenticationDetailsSource(this.authenticationDetailsSource); } SessionAuthenticationStrategy sessionAuthenticationStrategy = (SessionAuthenticationStrategy)http.getSharedObject(SessionAuthenticationStrategy.class); if (sessionAuthenticationStrategy != null) { this.authFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy); } RememberMeServices rememberMeServices = (RememberMeServices)http.getSharedObject(RememberMeServices.class); if (rememberMeServices != null) { this.authFilter.setRememberMeServices(rememberMeServices); } SecurityContextConfigurer securityContextConfigurer = (SecurityContextConfigurer)http.getConfigurer(SecurityContextConfigurer.class); if (securityContextConfigurer != null && securityContextConfigurer.isRequireExplicitSave()) { SecurityContextRepository securityContextRepository = securityContextConfigurer.getSecurityContextRepository(); this.authFilter.setSecurityContextRepository(securityContextRepository); } this.authFilter.setSecurityContextHolderStrategy(this.getSecurityContextHolderStrategy()); F filter = (AbstractAuthenticationProcessingFilter)this.postProcess(this.authFilter); http.addFilter(filter); }说明:
this.authFilter.setAuthenticationManager((AuthenticationManager)http.getSharedObject(AuthenticationManager.class));方法中,(AuthenticationManager)http.getSharedObject(AuthenticationManager.class)获取到的是ProviderManager对象,该对象是在HttpSecurity类的beforeConfigure()方法中设置的 -
子类:
FormLoginConfigurer-
构造方法,3️⃣
public FormLoginConfigurer() { super(new UsernamePasswordAuthenticationFilter(), (String)null); this.usernameParameter("username"); this.passwordParameter("password"); }说明:该
FormLoginConfigurer对象会加入到HttpSecurity对象的configurers属性中
-
-
-
-
-
-
抽象类:
AbstractAuthenticationProcessingFilter-
属性:
private AuthenticationManager authenticationManager; -
方法:
public void setAuthenticationManager(AuthenticationManager authenticationManager),1️⃣2️⃣public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; }说明:该
authenticationManager为ProviderManager对象,会加入到UsernamePasswordAuthenticationFilter对象的authenticationManager属性中 -
子类:
UsernamePasswordAuthenticationFilter-
构造方法,5️⃣
public UsernamePasswordAuthenticationFilter() { super(DEFAULT_ANT_PATH_REQUEST_MATCHER); }说明:该
UsernamePasswordAuthenticationFilter对象会加入到FormLoginConfigurer对象的authFilter属性中
-
-
总结
// 伪代码
ProviderManager manager = new ProviderManager();
UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter = new UsernamePasswordAuthenticationFilter();
usernamePasswordAuthenticationFilter.authenticationManager = manager;
FormLoginConfigurer formLoginConfigurer = new FormLoginConfigurer();
formLoginConfigurer.authFilter = usernamePasswordAuthenticationFilter;
HttpSecurity httpSecurity = new HttpSecurity();
httpSecurity.configurers.put(FormLoginConfigurer.class, Arrays.asList(formLoginConfigurer));
httpSecurity.sharedObject.put(AuthenticationManager.class, manager);
如有不对,欢迎指正!
更多推荐


所有评论(0)