志宇-springSecurty
springSecurty啟動流程
首先EnableWebSecurity 注解導入了WebSecurityConfiguration配置類 @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 {}
首先看這個類org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration
代碼如下
代碼分析
上面代碼會創建一個 AutowireBeanFactoryObjectPostProcessor的代理類 WebSecurity
WebSecurity這個類可以向spring容器添加對象,同時還維護著一個LinkedHashMap用來存儲所有的WebSecurityConfigurerAdapter,WebSecurityConfigurerAdapter是配置springSecurity要繼承的類
接下來看這個類org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration
代碼如下
代碼分析
上面代碼會通過AutowireBeanFactoryObjectPostProcessor向spring容器注冊一個對象WebSecurityConfigurerAdapter,然后將WebSecurityConfigurerAdapter存儲到webSecurity中,
然后調用webSecurity的build方法,執行代碼如下
接下來依次分析 init()、beforeConfigure()、configure()、performBuild()方法,WebSecurityConfigurerAdapter中
此部分代碼比較多分部分析,代碼如下
public void init(final WebSecurity web) throws Exception {//創建一個HttpSecurityfinal HttpSecurity http = getHttp();web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class);//給WebSecurity設置一個攔截器web.securityInterceptor(securityInterceptor);});protected final HttpSecurity getHttp() throws Exception {//首先創建DefaultAuthenticationEventPublisher對象然后將這個對象添加到spring容器中//此對象維護著一個exceptionMappings對象,存儲異常和ApplicationEventDefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher());//將eventPublisher給localConfigureAuthenticationBldr代理//localConfigureAuthenticationBldr 也就是 AuthenticationManagerBuilder對象localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);AuthenticationManager authenticationManager = authenticationManager();authenticationBuilder.parentAuthenticationManager(authenticationManager);authenticationBuilder.authenticationEventPublisher(eventPublisher);Map<Class<?>, Object> sharedObjects = createSharedObjects();//創建http對象,其中FilterComparator中存儲了32個過濾器 http = new HttpSecurity(objectPostProcessor, authenticationBuilder,sharedObjects);if (!disableDefaults) {// 往HttpSecurity添加一些列的 配置類//CsrfConfigurer//ExceptionHandlingConfigurer//HeadersConfigurer//SessionManagementConfigurer//SecurityContextConfigurer//RequestCacheConfigurer//AnonymousConfigurer//ServletApiConfigurer//DefaultLoginPageConfigurer//LogoutConfigurerhttp.csrf().and().addFilter(new WebAsyncManagerIntegrationFilter()).exceptionHandling().and().headers().and().sessionManagement().and().securityContext().and().requestCache().and().anonymous().and().servletApi().and().apply(new DefaultLoginPageConfigurer<>()).and().logout();ClassLoader classLoader = this.context.getClassLoader();//添加一些默認配置List<AbstractHttpConfigurer> defaultHttpConfigurers =SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);//添加一些默認配置for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {http.apply(configurer);}}//調用自己配置的 configure方法,添加一些Configurerconfigure(http);return http;}protected AuthenticationManager authenticationManager() throws Exception {//這里僅僅用一個標志位不用鎖 也不會線程不安全//因為build 方法中通過 //if(AtomicBoolean.compareAndSet(false, true)){}if (!authenticationManagerInitialized) {//調用配置的configure方法//方法中我們給 provider的 UserDetailsService,passwordEncoder 成員變量賦值//同時添加DaoAuthenticationConfigurer 對象configure(localConfigureAuthenticationBldr);if (disableLocalConfigureAuthenticationBldr) {//如果我們沒有重寫configure方法則調用這里邏輯authenticationManager = authenticationConfiguration.getAuthenticationManager();}else {//localConfigureAuthenticationBldr 也就是 AuthenticationManagerBuilder對象//AuthenticationManagerBuilder中的configurers中只有一個對象DaoAuthenticationConfigurer//調用 DaoAuthenticationConfigurer 的doBuild方法//方法中會通過包裝創建一個ProviderManagerauthenticationManager = localConfigureAuthenticationBldr.build();}authenticationManagerInitialized = true;}return authenticationManager;}private void configure() throws Exception {Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();//循環調用所有配置類的方法//有的configurer中的configure方法會添加攔截器for (SecurityConfigurer<O, B> configurer : configurers) {configurer.configure((B) this);}}protected Filter performBuild() throws Exception {Assert.state(!securityFilterChainBuilders.isEmpty(),() -> "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "+ "Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. "+ "More advanced users can invoke "+ WebSecurity.class.getSimpleName()+ ".addSecurityFilterChainBuilder directly");int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();List<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize);for (RequestMatcher ignoredRequest : ignoredRequests) {securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));}//securityFilterChainBuilder中存儲所有的 HttpSecurityfor (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {//在方法中循環遍歷所有HttpSecurity中configurers //configurers 是webSecurity中存儲WebSecurityConfigurerAdapter的LinkedHashMap//調用所有配置類的configurer 的 init configure 方法//securityFilterChains.add(securityFilterChainBuilder.build());}//通過FilterChainProxy對securityFilterChains進行包裝FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);if (httpFirewall != null) {filterChainProxy.setFirewall(httpFirewall);}filterChainProxy.afterPropertiesSet();Filter result = filterChainProxy;postBuildAction.run();return result;} }上面代碼通過CsrfConfigurer、ExceptionHandlingConfigurer、HeadersConfigurer、SessionManagementConfigurer、SecurityContextConfigurer、RequestCacheConfigurer、AnonymousConfigurer 、ServletApiConfigurer、DefaultLoginPageConfigurer、LogoutConfigurer 等對象的 configure 方法 添加過濾器,我們配置對應的Configurer對象就能修改過濾器要攔截的內容,過濾器如下
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
MyTokenFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
總結
以上是生活随笔為你收集整理的志宇-springSecurty的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: areas ajax路由,Areas(区
- 下一篇: 云服务器ECS入门