- 浏览: 193847 次
- 性别:
- 来自: 南京
文章分类
最新评论
前言
在上一篇文章中通过对EnableWebSecurity注解中的配置类WebSecurityConfiguration的探讨,我们知道了filter各种各样的filter以及鉴权用的AccessDecisionManager是怎么加载进来的,但是具体用来认证的AuthenticationManager怎么加载还没有说明,这篇文章,我们就重点分析下各种各样的AuthenticationManager是怎么加载的。
通过上一篇我们知道EnableWebSecurity这个注解除了引入WebSecurityConfiguration这个配置类外,还引入了EnableGlobalAuthentication这个注解,和认证机制相关的秘密就在这个注解中,下面我们重点看看这个注解是怎么做的
环境:
spring-boot version:1.5.4.RELEASE
1..@EnableGlobalAuthentication
这个注解主要是引入了AuthenticationConfiguration这个配置类
2. AuthenticationConfiguration类
这个配置类最重要的就是上面的这一部分,主要做了下面四件事
getAuthenticationManager()这个方法的调用,我们需要重新看下WebSecurityConfigurerAdapter这个类的getHttp()方法
3. WebSecurityConfigurerAdapter
调用过程就是上面这两段代码,默认情况下disableLocalConfigureAuthenticationBldr是true,所以最终调用了authenticationConfiguration.getAuthenticationManager();即上面说的那个方法。
在getAuthenticationManager()方法中,主要是调用AuthenticationManagerBuilder这个类的build方法来获取一个AuthenticationManager,AuthenticationManagerBuilder类和httpSecurity、webSecurity类一样都是继承自AbstractConfiguredSecurityBuilder,所以build的过程也一样 init->configure->performBuild.在这个过程中会依次调用注入的GlobalAuthenticationConfigurerAdapter这些类的configure方法。
下面以InitializeUserDetailsBeanManagerConfigurer这个类来说明
4.InitializeUserDetailsBeanManagerConfigurer
这个类在init时向AuthenticationManagerBuilder中新追加了一个InitializeUserDetailsManagerConfigurer类,可以看到在这个类中为我们创建了一个DaoAuthenticationProvider,并把创建好的DaoAuthenticationProvider放入到了AuthenticationManagerBuilder中,在创建过程中使用了applicationcontext中定义过的UserDetailsService和PasswordEncoder类,这就是我们在很多例子中看到的定义一个UserDetailsService就可以实现自己认证逻辑的原因。
其他的Configure实现逻辑差不多,只不过做的事情不一样,就不再一一展开,下面主要看下AuthenticationManagerBuilder的performBuild()方法
5. AuthenticationManagerBuilder
在这个方法中用我们之前用的authenticationProviders创建了一个ProviderManager类,还设置了一个parentAuthenticationManager参数,在这个阶段parentAuthenticationManager属性的值是null,下面接着说这个字段在什么时候用。
这个设置还是在WebSecurityConfigurerAdapter这个类的getHttp()方法中,
在这个方法中调用authenticationManager()方法后接着就将创建好的AuthenticationManager设置成authenticationBuilder的parentAuthenticationManager属性,即我们刚才分析的创建过程只是创建了一个parentAuthenticationManager,那在什么时候再继续利用authenticationBuilder创建一个真实的authenticationManager呢,答案在HttpSecurity类中
6. HttpSecurity
通过上一篇文章,我们知道在HttpSecurity的build方法时,会先调用这个类的beforeConfigure方法,这个时候就会将我们继承了WebSecurityConfigurerAdapter中定义的各种认证方式给注册进来。如我们想用INMEMORY认证方式时可以这样配置
或者是利用cas认证时
因此正常情况下ProviderManager都会有一个parent属性,这个也是为什么在ProviderManager 这个类的authenticate方法中会判断如果当前ProviderManager不能认证成功的话,会再用parent来认证的原因。
至此,spring-security java config中主要的组件加载逻辑已经讲完。
在上一篇文章中通过对EnableWebSecurity注解中的配置类WebSecurityConfiguration的探讨,我们知道了filter各种各样的filter以及鉴权用的AccessDecisionManager是怎么加载进来的,但是具体用来认证的AuthenticationManager怎么加载还没有说明,这篇文章,我们就重点分析下各种各样的AuthenticationManager是怎么加载的。
通过上一篇我们知道EnableWebSecurity这个注解除了引入WebSecurityConfiguration这个配置类外,还引入了EnableGlobalAuthentication这个注解,和认证机制相关的秘密就在这个注解中,下面我们重点看看这个注解是怎么做的
环境:
spring-boot version:1.5.4.RELEASE
1..@EnableGlobalAuthentication
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) @Target(value = { java.lang.annotation.ElementType.TYPE }) @Documented @Import(AuthenticationConfiguration.class) @Configuration public @interface EnableGlobalAuthentication { }
这个注解主要是引入了AuthenticationConfiguration这个配置类
2. AuthenticationConfiguration类
... @Bean public AuthenticationManagerBuilder authenticationManagerBuilder( ObjectPostProcessor<Object> objectPostProcessor) { return new AuthenticationManagerBuilder(objectPostProcessor); } @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); 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; } ...
这个配置类最重要的就是上面的这一部分,主要做了下面四件事
- 注册一个AuthenticationManagerBuilder类型的bean
- 注册了三个实现了GlobalAuthenticationConfigurerAdapter的bean:GlobalAuthenticationConfigurerAdapter、InitializeUserDetailsBeanManagerConfigurer、InitializeAuthenticationProviderBeanManagerConfigurer
- 定义了一个获取AuthenticationManager的方法getAuthenticationManager(),这个方法怎么调用下面会讲
- 通过setGlobalAuthenticationConfigurers这个方法,将实现了GlobalAuthenticationConfigurerAdapter这个抽象类的类注入到当前类中,就是我们上面说的三个bean,实际运行时发现除了上面三个类外,还有 另外两个bean也注入了进来
BootGlobalAuthenticationConfigurationAdapter和SpringBootAuthenticationConfigurerAdapter
下面就说下这两个bean是如何创建的
首先在spring-boot-autoconfigure-{version}.jar的META-INF/spring.factories中配置了springboot启动时自动加载的类
其中和spring security相关的有下面四个
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
和我们这两个bean相关的类是SecurityAutoConfiguration,这个自动配置类又引入了
SpringBootWebSecurityConfiguration
BootGlobalAuthenticationConfiguration
AuthenticationManagerConfiguration 这三个配置类
SpringBootWebSecurityConfiguration这个类的功能是只要我们把spring security相关的jar引入,就保证基本的spring security功能能使用,因为我们自己引入EnableWebSecurity,这个注解引入了WebSecurityConfiguration,所以这个配置类就不起作用了
在BootGlobalAuthenticationConfiguration 这个配置类中,就可以看到定义了我们要找的bean -BootGlobalAuthenticationConfiguration 这个bean的定义也是static的
AuthenticationManagerConfiguration 这个配置类定义了两个bean,其中一个就是我们要找的 SpringBootAuthenticationConfigurerAdapter 这个bean的定义也是static的
另一个就是非常重要的 AuthenticationManager这个bean的定义并且是@Primary的
调用的是 上面提到的AuthenticationConfiguration.getAuthenticationManager()这个方法,但是因为我们在WebSecurityConfigurerAdapter类中配置httpSecurity时已经调用过一次
所以这个调用这个方法会直接返回。
getAuthenticationManager()这个方法的调用,我们需要重新看下WebSecurityConfigurerAdapter这个类的getHttp()方法
3. WebSecurityConfigurerAdapter
protected final HttpSecurity getHttp() throws Exception { if (http != null) { return http; } DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor .postProcess(new DefaultAuthenticationEventPublisher()); localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher); AuthenticationManager authenticationManager = authenticationManager(); authenticationBuilder.parentAuthenticationManager(authenticationManager); Map<Class<? extends Object>, Object> sharedObjects = createSharedObjects(); http = new HttpSecurity(objectPostProcessor, authenticationBuilder, sharedObjects); ...... protected AuthenticationManager authenticationManager() throws Exception { if (!authenticationManagerInitialized) { configure(localConfigureAuthenticationBldr); if (disableLocalConfigureAuthenticationBldr) { authenticationManager = authenticationConfiguration .getAuthenticationManager(); } else { authenticationManager = localConfigureAuthenticationBldr.build(); } authenticationManagerInitialized = true; } return authenticationManager; }
调用过程就是上面这两段代码,默认情况下disableLocalConfigureAuthenticationBldr是true,所以最终调用了authenticationConfiguration.getAuthenticationManager();即上面说的那个方法。
在getAuthenticationManager()方法中,主要是调用AuthenticationManagerBuilder这个类的build方法来获取一个AuthenticationManager,AuthenticationManagerBuilder类和httpSecurity、webSecurity类一样都是继承自AbstractConfiguredSecurityBuilder,所以build的过程也一样 init->configure->performBuild.在这个过程中会依次调用注入的GlobalAuthenticationConfigurerAdapter这些类的configure方法。
下面以InitializeUserDetailsBeanManagerConfigurer这个类来说明
4.InitializeUserDetailsBeanManagerConfigurer
.... @Override public void init(AuthenticationManagerBuilder auth) throws Exception { auth.apply(new InitializeUserDetailsManagerConfigurer()); } class InitializeUserDetailsManagerConfigurer extends GlobalAuthenticationConfigurerAdapter { @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { if (auth.isConfigured()) { return; } UserDetailsService userDetailsService = getBeanOrNull( UserDetailsService.class); if (userDetailsService == null) { return; } PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService); if (passwordEncoder != null) { provider.setPasswordEncoder(passwordEncoder); } auth.authenticationProvider(provider); } ....
这个类在init时向AuthenticationManagerBuilder中新追加了一个InitializeUserDetailsManagerConfigurer类,可以看到在这个类中为我们创建了一个DaoAuthenticationProvider,并把创建好的DaoAuthenticationProvider放入到了AuthenticationManagerBuilder中,在创建过程中使用了applicationcontext中定义过的UserDetailsService和PasswordEncoder类,这就是我们在很多例子中看到的定义一个UserDetailsService就可以实现自己认证逻辑的原因。
其他的Configure实现逻辑差不多,只不过做的事情不一样,就不再一一展开,下面主要看下AuthenticationManagerBuilder的performBuild()方法
5. AuthenticationManagerBuilder
@Override protected ProviderManager performBuild() throws Exception { if (!isConfigured()) { logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null."); return null; } ProviderManager providerManager = new ProviderManager(authenticationProviders, parentAuthenticationManager); if (eraseCredentials != null) { providerManager.setEraseCredentialsAfterAuthentication(eraseCredentials); } if (eventPublisher != null) { providerManager.setAuthenticationEventPublisher(eventPublisher); } providerManager = postProcess(providerManager); return providerManager; }
在这个方法中用我们之前用的authenticationProviders创建了一个ProviderManager类,还设置了一个parentAuthenticationManager参数,在这个阶段parentAuthenticationManager属性的值是null,下面接着说这个字段在什么时候用。
这个设置还是在WebSecurityConfigurerAdapter这个类的getHttp()方法中,
在这个方法中调用authenticationManager()方法后接着就将创建好的AuthenticationManager设置成authenticationBuilder的parentAuthenticationManager属性,即我们刚才分析的创建过程只是创建了一个parentAuthenticationManager,那在什么时候再继续利用authenticationBuilder创建一个真实的authenticationManager呢,答案在HttpSecurity类中
6. HttpSecurity
@Override protected void beforeConfigure() throws Exception { setSharedObject(AuthenticationManager.class, getAuthenticationRegistry().build()); }
通过上一篇文章,我们知道在HttpSecurity的build方法时,会先调用这个类的beforeConfigure方法,这个时候就会将我们继承了WebSecurityConfigurerAdapter中定义的各种认证方式给注册进来。如我们想用INMEMORY认证方式时可以这样配置
public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void auth(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("chengf").password("sso").authorities("ROLE_USER", "ROLE_ADMIN").and() .withUser("user").password("password").authorities("ROLE_USER"); } }
或者是利用cas认证时
@Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable().authorizeRequests().anyRequest().hasRole("USER").and() .exceptionHandling().authenticationEntryPoint(casEntryPoint()).and() .addFilter(casFilter()) .authenticationProvider(casAuthenticationProvider()); }
因此正常情况下ProviderManager都会有一个parent属性,这个也是为什么在ProviderManager 这个类的authenticate方法中会判断如果当前ProviderManager不能认证成功的话,会再用parent来认证的原因。
至此,spring-security java config中主要的组件加载逻辑已经讲完。
发表评论
-
spring-security(二十五)鉴权
2018-03-27 11:21 1600前言 本文将详细探讨spring security中的鉴权 ... -
test
2018-03-19 21:20 0什么是服务发现 ... -
spring-security(二十四)CSRF
2018-03-24 09:54 81591.什么是CSRF攻击 下面我们以一个具体的例子来说明这种常见 ... -
spring-security(二十三)Remember-Me认证
2018-03-09 21:06 1340前言: Remember-me认证方式指的是能在不同的会话 ... -
spring-security(二十二)基本认证和摘要认证
2018-03-06 16:58 1801前言: 在web应用中,非常流行以基本认证和摘要认证作为备 ... -
spring-security(二十一)核心Filter-UsernamePasswordAuthenticationFilter
2018-03-04 11:05 1237一、UsernamePasswordAuthenticatio ... -
spring-security(二十)核心Filter-SecurityContextPersistenceFilter
2018-02-28 21:40 1131一、SecurityContextPersistenceFil ... -
spring-security(十九)核心Filter-ExceptionTranslationFilter
2018-02-27 16:31 2060前言: 在spring的安全 ... -
spring-security(十八)核心Filter-FilterSecurityInterceptor
2018-02-25 10:59 2344前言: 当用spring secur ... -
spring-security(二十六)整合CAS 实现SSO
2018-04-05 18:09 12421.cas 认证流程 2.spring security ... -
spring-security(十七)Filter顺序及简介
2018-02-22 18:16 7901前言: spring security在 ... -
spring-security(十六)Filter配置原理
2018-02-21 15:18 2386前言: spring security最常见的应用场景还是 ... -
spring-security(十五) Password编码
2018-02-19 15:15 1225前言: 在实际应用中 ... -
spring-security(十四)UserDetailsService
2018-02-19 11:35 1471前言: 作为spring security的核心类,大多数 ... -
spring-security(十三)核心服务类
2018-02-18 16:46 1412前言: 在之前的篇章中我们已经讲述了spring secu ... -
spring-security(十二)鉴权方式概述
2018-02-18 10:42 2526前言: 本文主要讲述在spring security鉴权的 ... -
spring-security(十一)Web应用认证过程
2018-02-17 17:17 1238前言: 本文将探讨当 ... -
spring-security(十)基本认证过程
2018-02-17 13:55 2106前言: 在spring security中认证具体指的是什 ... -
spring-security(九)-核心组件
2018-02-17 10:46 868前言: 本文主要介绍在spring security中的几 ... -
spring-security(八)java config-sample之cas client
2018-02-16 11:26 2068前言: SSO英文全称Single Sign On,单点登 ...
相关推荐
赠送jar包:spring-security-config-5.0.7.RELEASE.jar; 赠送原API文档:spring-security-config-5.0.7.RELEASE-javadoc.jar; 赠送源代码:spring-security-config-5.0.7.RELEASE-sources.jar; 赠送Maven依赖信息...
赠送jar包:spring-security-config-5.5.2.jar; 赠送原API文档:spring-security-config-5.5.2-javadoc.jar; 赠送源代码:spring-security-config-5.5.2-sources.jar; 赠送Maven依赖信息文件:spring-security-...
赠送jar包:spring-security-config-5.3.9.RELEASE.jar; 赠送原API文档:spring-security-config-5.3.9.RELEASE-javadoc.jar; 赠送源代码:spring-security-config-5.3.9.RELEASE-sources.jar; 赠送Maven依赖信息...
赠送jar包:spring-security-config-5.2.0.RELEASE.jar; 赠送原API文档:spring-security-config-5.2.0.RELEASE-javadoc.jar; 赠送源代码:spring-security-config-5.2.0.RELEASE-sources.jar; 赠送Maven依赖信息...
赠送jar包:spring-security-config-5.6.1.jar; 赠送原API文档:spring-security-config-5.6.1-javadoc.jar; 赠送源代码:spring-security-config-5.6.1-sources.jar; 赠送Maven依赖信息文件:spring-security-...
赠送jar包:spring-security-config-4.2.8.RELEASE.jar; 赠送原API文档:spring-security-config-4.2.8.RELEASE-javadoc.jar; 赠送源代码:spring-security-config-4.2.8.RELEASE-sources.jar; 包含翻译后的...
赠送jar包:spring-security-crypto-5.6.1.jar; 赠送原API文档:spring-security-crypto-5.6.1-javadoc.jar; 赠送源代码:spring-security-crypto-5.6.1-sources.jar; 赠送Maven依赖信息文件:spring-security-...
赠送jar包:spring-security-crypto-5.5.2.jar; 赠送原API文档:spring-security-crypto-5.5.2-javadoc.jar; 赠送源代码:spring-security-crypto-5.5.2-sources.jar; 赠送Maven依赖信息文件:spring-security-...
赠送jar包:spring-security-oauth2-2.3.5.RELEASE.jar; 赠送原API文档:spring-security-oauth2-2.3.5.RELEASE-javadoc.jar; 赠送源代码:spring-security-oauth2-2.3.5.RELEASE-sources.jar; 赠送Maven依赖信息...
赠送jar包:spring-security-core-5.3.9.RELEASE.jar; 赠送原API文档:spring-security-core-5.3.9.RELEASE-javadoc.jar; 赠送源代码:spring-security-core-5.3.9.RELEASE-sources.jar; 赠送Maven依赖信息文件:...
赠送jar包:spring-security-jwt-1.0.10.RELEASE.jar; 赠送原API文档:spring-security-jwt-1.0.10.RELEASE-javadoc.jar; 赠送源代码:spring-security-jwt-1.0.10.RELEASE-sources.jar; 赠送Maven依赖信息文件:...
赠送jar包:spring-security-rsa-1.0.10.RELEASE.jar; 赠送原API文档:spring-security-rsa-1.0.10.RELEASE-javadoc.jar; 赠送源代码:spring-security-rsa-1.0.10.RELEASE-sources.jar; 赠送Maven依赖信息文件:...
赠送jar包:spring-security-core-5.2.0.RELEASE.jar; 赠送原API文档:spring-security-core-5.2.0.RELEASE-javadoc.jar; 赠送源代码:spring-security-core-5.2.0.RELEASE-sources.jar; 赠送Maven依赖信息文件:...
赠送jar包:spring-security-config-5.0.7.RELEASE.jar; 赠送原API文档:spring-security-config-5.0.7.RELEASE-javadoc.jar; 赠送源代码:spring-security-config-5.0.7.RELEASE-sources.jar; 赠送Maven依赖信息...
赠送jar包:spring-security-config-5.6.1.jar; 赠送原API文档:spring-security-config-5.6.1-javadoc.jar; 赠送源代码:spring-security-config-5.6.1-sources.jar; 赠送Maven依赖信息文件:spring-security-...
赠送jar包:spring-security-core-5.5.2.jar; 赠送原API文档:spring-security-core-5.5.2-javadoc.jar; 赠送源代码:spring-security-core-5.5.2-sources.jar; 赠送Maven依赖信息文件:spring-security-core-...
赠送jar包:spring-security-core-5.0.7.RELEASE.jar; 赠送原API文档:spring-security-core-5.0.7.RELEASE-javadoc.jar; 赠送源代码:spring-security-core-5.0.7.RELEASE-sources.jar; 赠送Maven依赖信息文件:...
赠送jar包:spring-security-web-5.2.0.RELEASE.jar; 赠送原API文档:spring-security-web-5.2.0.RELEASE-javadoc.jar; 赠送源代码:spring-security-web-5.2.0.RELEASE-sources.jar; 赠送Maven依赖信息文件:...
赠送jar包:spring-security-oauth2-2.3.5.RELEASE.jar; 赠送原API文档:spring-security-oauth2-2.3.5.RELEASE-javadoc.jar; 赠送源代码:spring-security-oauth2-2.3.5.RELEASE-sources.jar; 赠送Maven依赖信息...
10. **spring-security-config-3.1.2.RELEASE.jar**:提供了基于XML或Java的配置方式,用于定义安全规则和策略,如定义访问控制列表,自定义过滤器链等。 通过以上这些jar包,我们可以深入研究Spring Security Web...