栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Security源码学习——全局配置器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Security源码学习——全局配置器

前言

SecurityConfigurer 在 Spring Security 中是一个非常重要的角色。Spring Security 过滤器链中的每一个过滤器,都是通过 xxxConfigurer 来进行配置的,而这些 xxxConfigurer 实际上都是 SecurityConfigurer 的实现。

public interface SecurityConfigurer> {

 //一个初始化方法
 void init(B builder) throws Exception;

//一个配置方法。这里只是规范了方法的定义,具体的实现则在不同的实现类中
 void configure(B builder) throws Exception;
}

SecurityConfigurer 有三种类型实现类:SecurityConfigurerAdapter,GlobalAuthenticationConfigurerAdapter和WebSecurityConfigurer

而本文所讲的全局配置器GlobalAuthenticationConfigurerAdapter

一、GlobalAuthenticationConfigurerAdapter

GlobalAuthenticationConfigurerAdapter 看名字就知道是一个跟全局配置有关的东西,它本身实现了 SecurityConfigurerAdapter 接口,但是并未对方法做具体的实现,只是将泛型具体化了:

@Order(100)
public abstract class GlobalAuthenticationConfigurerAdapter implements SecurityConfigurer {

 public void init(AuthenticationManagerBuilder auth) throws Exception { }

 public void configure(AuthenticationManagerBuilder auth) throws Exception { }
}

可以看到,SecurityConfigurer 中的泛型,现在明确成了 AuthenticationManager 和 AuthenticationManagerBuilder。所以 GlobalAuthenticationConfigurerAdapter 的实现类将来主要是和配置 AuthenticationManager 有关。当然也包括默认的用户名密码也是由它的实现类来进行配置的。

我们在 Spring Security 中使用的 AuthenticationManager 其实可以分为两种,一种是局部的,另一种是全局的,这里主要是全局的配置。

二、InitializeUserDetailsBeanManagerConfigurer
@Order(InitializeUserDetailsBeanManagerConfigurer.DEFAULT_ORDER)
class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationConfigurerAdapter {

	static final int DEFAULT_ORDER = Ordered.LOWEST_PRECEDENCE - 5000;
	private final ApplicationContext context;

	InitializeUserDetailsBeanManagerConfigurer(ApplicationContext context) {
		this.context = context;
	}

	@Override
	public void init(AuthenticationManagerBuilder auth) throws Exception {
	    //创建其内部类InitializeUserDetailsManagerConfigurer
		auth.apply(new InitializeUserDetailsManagerConfigurer());
	}
	class InitializeUserDetailsManagerConfigurer extends GlobalAuthenticationConfigurerAdapter {
		@Override
		public void configure(AuthenticationManagerBuilder auth) throws Exception {
			if (auth.isConfigured()) {
				return;
			}
			//从容器中获取UserDetailsService,如果没有直接返回
			UserDetailsService userDetailsService = getBeanOrNull( UserDetailsService.class);
			if (userDetailsService == null) {return;}
			//从容器中获取PasswordEncoder
			PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
		    //从容器中获取UserDetailsPasswordService
			UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class);
            //创建DaoAuthenticationProvider,将3个类配置进去
			DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
			provider.setUserDetailsService(userDetailsService);
			if (passwordEncoder != null) {
				provider.setPasswordEncoder(passwordEncoder);
			}
			if (passwordManager != null) {
				provider.setUserDetailsPasswordService(passwordManager);
			}
			provider.afterPropertiesSet();
			auth.authenticationProvider(provider);
		}
	}
}

他的注册发生在配置类AuthenticationConfiguration中

@Configuration(proxyBeanMethods = false)
@import(ObjectPostProcessorConfiguration.class)
public class AuthenticationConfiguration {
    @Bean
	public static InitializeUserDetailsBeanManagerConfigurer initializeUserDetailsBeanManagerConfigurer(ApplicationContext context) {
		return new InitializeUserDetailsBeanManagerConfigurer(context);
	}
}
二、InitializeAuthenticationProviderBeanManagerConfigurer
@Order(InitializeAuthenticationProviderBeanManagerConfigurer.DEFAULT_ORDER)
class InitializeAuthenticationProviderBeanManagerConfigurer extends GlobalAuthenticationConfigurerAdapter {

	InitializeAuthenticationProviderBeanManagerConfigurer(ApplicationContext context) {
		this.context = context;
	}

	@Override
	public void init(AuthenticationManagerBuilder auth) throws Exception {
	   //创建内部类InitializeUserDetailsManagerConfigurer
		auth.apply(new InitializeUserDetailsManagerConfigurer());
	}

	class InitializeUserDetailsManagerConfigurer extends GlobalAuthenticationConfigurerAdapter {
		@Override
		public void configure(AuthenticationManagerBuilder auth) {
			if (auth.isConfigured()) {
				return;
			}
			//从容器中获取AuthenticationProvider,如果没有直接返回
			AuthenticationProvider authenticationProvider = getBeanOrNull( AuthenticationProvider.class);
			if (authenticationProvider == null) {
				return;
			}
			auth.authenticationProvider(authenticationProvider);
		}
		//忽略方法。。。。
	}
}

他的注册也发生在配置类AuthenticationConfiguration中

@Configuration(proxyBeanMethods = false)
@import(ObjectPostProcessorConfiguration.class)
public class AuthenticationConfiguration {

    @Bean
	public static InitializeAuthenticationProviderBeanManagerConfigurer initializeAuthenticationProviderBeanManagerConfigurer(ApplicationContext context) {
		return new InitializeAuthenticationProviderBeanManagerConfigurer(context);
	}
}

EnableGlobalAuthenticationAutowiredConfigurer只是为了记录标注@EnableGlobalAuthentication的类

注意GlobalAuthenticationConfigurerAdapter子类的注册都在配置类AuthenticationConfiguration中,而AuthenticationConfiguration是通过
@EnableGlobalAuthentication引入的,所以@EnableGlobalAuthentication注解是开启全局配置器的关键,当然了,在springboot环境,我们不需要手动配置@EnableGlobalAuthentication,因为springboot帮我们引入了

@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(WebSecurityConfigurerAdapter.class)
@ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
//继承了@EnableGlobalAuthentication
@EnableWebSecurity
public class WebSecurityEnablerConfiguration {

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/299428.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号