目录
AbstractConfiguredSecurityBuilder
AuthenticationManagerBuilder配置。
https://github.com/spring-cloud/spring-cloud-security/tree/v2.2.1.RELEASE
Spring Security的引入
在使用Spring Security时,会定义一个WebSecurityConfigurerAdapter的子类,并同时加上注解@EnableWebSecurity。
// org.springframework.security.config.annotation.web.configuration;
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@EnableWebSecurity用于引入security功能,WebSecurityConfigurerAdapter实现类用于扩展功能。
@Import({ WebSecurityConfiguration.class,
SpringWebMvcImportSelector.class,
OAuth2ImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
/**
* Controls debugging support for Spring Security. Default is false.
* @return if true, enables debug support with Spring Security
*/
boolean debug() default false;
}
@EnableWebSecurity又会引入@EnableGlobalAuthentication
@Import(AuthenticationConfiguration.class)
@Configuration
public @interface EnableGlobalAuthentication {
}
因此会导入几个类:
- AuthenticationConfiguration。
- WebSecurityConfiguration。引入FilterChain。
- SpringWebMvcImportSelector。判断是否引入了Spring MVC。
- OAuth2ImportSelector。判断是否引入了OAuth2。
AuthenticationConfiguration
@Import(ObjectPostProcessorConfiguration.class)
public class AuthenticationConfiguration {
@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);
}
}
WebSecurityConfiguration
引入 FilterChain。
创建名称为springSecurityFilterChain的Filter
//public static final String DEFAULT_FILTER_NAME = "springSecurityFilterChain";
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
//判断是否自定义了SecurityConfigurer
boolean hasConfigurers = webSecurityConfigurers != null
&& !webSecurityConfigurers.isEmpty();
if (!hasConfigurers) {
//如果没有自定义,则使用默认的。
WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
.postProcess(new WebSecurityConfigurerAdapter() {
});
webSecurity.apply(adapter);
}
//builder 返回一个Filter
return webSecurity.build();
}
设置FilterChain的配置信息。
创建了一个WebSecurity。
@Autowired(required = false)
public void setFilterChainProxySecurityConfigurer(
ObjectPostProcessor<Object> objectPostProcessor,
@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
throws Exception {
//创建webSecurity
webSecurity = objectPostProcessor
.postProcess(new WebSecurity(objectPostProcessor));
if (debugEnabled != null) {
webSecurity.debug(debugEnabled);
}
//webSecurityConfigurers排序。通过@Order注解。
webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);
//对Order进行比较是否有相同的(保证不相同),由于前面进行了排序,只要比较前后有相同的就可以
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 应用配置。
webSecurity.apply(webSecurityConfigurer);
}
this.webSecurityConfigurers = webSecurityConfigurers;
}
获取configurers。一般返回的就是自定义的WebSecurityConfigurer。
@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers
public List<SecurityConfigurer<Filter, WebSecurity>> getWebSecurityConfigurers() {
List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new ArrayList<>();
//获取所有WebSecurityConfigurer的实现类。
Map<String, WebSecurityConfigurer> beansOfType = beanFactory
.getBeansOfType(WebSecurityConfigurer.class);
for (Entry<String, WebSecurityConfigurer> entry : beansOfType.entrySet()) {
webSecurityConfigurers.add(entry.getValue());
}
return webSecurityConfigurers;
}
WebSecurity
Filter的创建,最终是通过WebSecurity的实例的build()方法实现。
WebSecurity的类继承如下图:
- SecurityBuilder定义了构建的接口标准
- AbstractSecurityBuilder实现build方法,用AtomicBoolean的变量building保证多线程情况下,操作的原子性。此处采用的是模板模式。定义了doBuild()抽象方法
- AbstractConfiguredSecurityBuilder 继承AbstractSecurityBuilder实现doBuild()方法,也采用模板模式,定义了实现的具体的步骤。
public interface SecurityBuilder<O> {
O build() throws Exception;
}
public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
//用于控制并发。
private AtomicBoolean building = new AtomicBoolean();
private O object;
public final O build() throws Exception {
if (this.building.compareAndSet(false, true)) {
this.object = doBuild();
return this.object;
}
throw new AlreadyBuiltException("This object has already been built");
}
public final O getObject() {
if (!this.building.get()) {
throw new IllegalStateException("This object has not been built");
}
return this.object;
}
//由子类具体实现build。
protected abstract O doBuild() throws Exception;
}
AbstractConfiguredSecurityBuilder
属性
public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>
extends AbstractSecurityBuilder<O> {
//SecurityConfigurer 列表。
private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers = new LinkedHashMap<>();
private final List<SecurityConfigurer<O, B>> configurersAddedInInitializing = new ArrayList<>();
private final Map<Class<?>, Object> sharedObjects = new HashMap<>();
private final boolean allowConfigurersOfSameType;
//当前状态。
private BuildState buildState = BuildState.UNBUILT;
private ObjectPostProcessor<Object> objectPostProcessor;
}
doBuild()方法
doBuild()方法的步骤:
- beforeInit。空实现,可由子类覆盖。
- init。
- beforeConfigure。空实现,可由子类覆盖。
- configure
- performBuild。由子类实现。
@Override
protected final O doBuild() throws Exception {
synchronized (configurers) {
buildState = BuildState.INITIALIZING;
beforeInit();
init();
buildState = BuildState.CONFIGURING;
beforeConfigure();
configure();
buildState = BuildState.BUILDING;
O result = performBuild();
buildState = BuildState.BUILT;
return result;
}
}
private Collection<SecurityConfigurer<O, B>> getConfigurers() {
List<SecurityConfigurer<O, B>> result = new ArrayList<>();
for (List<SecurityConfigurer<O, B>> configs : this.configurers.values()) {
result.addAll(configs);
}
return result;
}
init()方法
private void init() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
//循环所有的configurer ,调用其初始化。
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.init((B) this);
}
for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) {
configurer.init((B) this);
}
}
configure()方法
private void configure() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
//循环调用configurer 的configure()方法。
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.configure((B) this);
}
}
apply()方法
apply方法用于设置SecurityConfigurer的属性,并加入到此builder的configurers中。
public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer) throws Exception {
configurer.addObjectPostProcessor(objectPostProcessor);
configurer.setBuilder((B) this);
add(configurer);
return configurer;
}
public <C extends SecurityConfigurer<O, B>> C apply(C configurer) throws Exception {
add(configurer);
return configurer;
}
WebSecurity
属性
//忽略权限控制的请求 Matcher。
private final List<RequestMatcher> ignoredRequests = new ArrayList<>();
//构造SecurityFilterChain 的Buidler列表。
private final List<SecurityBuilder<? extends SecurityFilterChain>> securityFilterChainBuilders = new ArrayList<>();
private IgnoredRequestConfigurer ignoredRequestRegistry;
private FilterSecurityInterceptor filterSecurityInterceptor;
private HttpFirewall httpFirewall;
private boolean debugEnabled;
private WebInvocationPrivilegeEvaluator privilegeEvaluator;
private DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
private SecurityExpressionHandler<FilterInvocation> expressionHandler = defaultWebSecurityExpressionHandler;
private Runnable postBuildAction = () -> {
};
performBuild()
真实构造FilterChain:FilterChainProxy
@Override
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();
//securityFilterChains
List<SecurityFilterChain> securityFilterChains = new ArrayList<>(
chainSize);
//如果是ignoredRequest类型的,那么久添加默认过滤器链(DefaultSecurityFilterChain)
for (RequestMatcher ignoredRequest : ignoredRequests) {
securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
}
//如果是securityFilterChainBuilder类型的,那么通过securityFilterChainBuilder的build()方法来构建过滤器链
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
securityFilterChains.add(securityFilterChainBuilder.build());
}
//将过滤器链交给一个过滤器链代理对象,此代理对象里面存储的是所有FilterChain。
FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
if (httpFirewall != null) {
filterChainProxy.setFirewall(httpFirewall);
}
filterChainProxy.afterPropertiesSet();
Filter result = filterChainProxy;
if (debugEnabled) {
result = new DebugFilter(filterChainProxy);
}
//构造完后处理。
postBuildAction.run();
return result;
}
WebSecurityConfigurerAdapter
类图
public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {
void init(B builder) throws Exception;
void configure(B builder) throws Exception;
}
WebSecurityConfigurer构造的是Filter的实例。
public interface WebSecurityConfigurer<T extends SecurityBuilder<Filter>> extends
SecurityConfigurer<Filter, T> {
}
属性
使用WebSecurity作为Filter的builder。
@Order(100)
public abstract class WebSecurityConfigurerAdapter implements
WebSecurityConfigurer<WebSecurity> {
private ApplicationContext context;
private ContentNegotiationStrategy contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
private ObjectPostProcessor<Object> objectPostProcessor = new ObjectPostProcessor<Object>() {
public <T> T postProcess(T object) {
throw new IllegalStateException(
ObjectPostProcessor.class.getName()
+ " is a required bean. Ensure you have used @EnableWebSecurity and @Configuration");
}
};
private AuthenticationConfiguration authenticationConfiguration;
private AuthenticationManagerBuilder authenticationBuilder;
private AuthenticationManagerBuilder localConfigureAuthenticationBldr;
private boolean disableLocalConfigureAuthenticationBldr;
private boolean authenticationManagerInitialized;
private AuthenticationManager authenticationManager;
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
private HttpSecurity http;
//是否可使用默认值。
private boolean disableDefaults;
init()方法
通过getHttp()方法构造HttpSecurity,并设置为WebSecurity的builder。
public void init(final WebSecurity web) throws Exception {
//构造 HttpSecurity
final HttpSecurity http = getHttp();
//添加chain builder,类型为SecurityBuilder<? extends SecurityFilterChain>。
web.addSecurityFilterChainBuilder(http)
.postBuildAction(() -> {
FilterSecurityInterceptor securityInterceptor = http
.getSharedObject(FilterSecurityInterceptor.class);
web.securityInterceptor(securityInterceptor);
});
}
configure()方法
空实现。子类可覆盖。
public void configure(WebSecurity web) throws Exception {
}
getHttp()方法
protected final HttpSecurity getHttp() throws Exception {
if (http != null) {
return http;
}
//S1:
DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor
.postProcess(new DefaultAuthenticationEventPublisher());
localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);
//S2:
AuthenticationManager authenticationManager = authenticationManager();
authenticationBuilder.parentAuthenticationManager(authenticationManager);
authenticationBuilder.authenticationEventPublisher(eventPublisher);
Map<Class<?>, Object> sharedObjects = createSharedObjects();
//S3:
http = new HttpSecurity(objectPostProcessor, authenticationBuilder,
sharedObjects);
if (!disableDefaults) {
//S4:
// @formatter:off
http
.csrf().and()
.addFilter(new WebAsyncManagerIntegrationFilter())
.exceptionHandling().and()
.headers().and()
.sessionManagement().and()
.securityContext().and()
.requestCache().and()
.anonymous().and()
.servletApi().and()
.apply(new DefaultLoginPageConfigurer<>()).and()
.logout();
// @formatter:on
ClassLoader classLoader = this.context.getClassLoader();
//加载所有的AbstractHttpConfigurer子类。并应用apply方法。
List<AbstractHttpConfigurer> defaultHttpConfigurers =
SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);
for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
http.apply(configurer);
}
}
//S5:
configure(http);
return http;
}
步骤:
S1:
S2:构造AuthenticationManager 。
S3:构造HttpSecurity。
S4:如果不禁用默认值,则使用默认configurer设置HttpSecurity。
S5:配置HttpSecurity
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().and()
.httpBasic();
}
HttpSecurity
HttpSecurity是一个Builder,用于构造FilterChain。
类图
HttpSecurityBuilder
用于构造DefaultSecurityFilterChain。可维护Builder的属性。提供了设置 用于认证的bean的方法。
public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>> extends
SecurityBuilder<DefaultSecurityFilterChain> {
<C extends SecurityConfigurer<DefaultSecurityFilterChain, H>> C getConfigurer(
Class<C> clazz);
<C extends SecurityConfigurer<DefaultSecurityFilterChain, H>> C removeConfigurer(
Class<C> clazz);
<C> void setSharedObject(Class<C> sharedType, C object);
<C> C getSharedObject(Class<C> sharedType);
H authenticationProvider(AuthenticationProvider authenticationProvider);
H userDetailsService(UserDetailsService userDetailsService) throws Exception;
H addFilterAfter(Filter filter, Class<? extends Filter> afterFilter);
H addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter);
H addFilter(Filter filter);
}
HttpSecurity
属性
//请求匹配过滤的配置信息
private final RequestMatcherConfigurer requestMatcherConfigurer;
//过滤器列表
private List<Filter> filters = new ArrayList<>();
//匹配任何请求的匹配器
private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE;
//过滤器比较。
private FilterComparator comparator = new FilterComparator();
FilterComparator
用于Filter排序。并定义了常用Filter的Order顺序。初始值100,步长100。可以通过 方法在某个Filter前面后者后面加Filter。
final class FilterComparator implements Comparator<Filter>, Serializable {
public int compare(Filter lhs, Filter rhs) {
Integer left = getOrder(lhs.getClass());
Integer right = getOrder(rhs.getClass());
return left - right;
}
}
private static final int INITIAL_ORDER = 100;
private static final int ORDER_STEP = 100;
FilterComparator() {
Step order = new Step(INITIAL_ORDER, ORDER_STEP);
put(ChannelProcessingFilter.class, order.next());
put(ConcurrentSessionFilter.class, order.next());
put(WebAsyncManagerIntegrationFilter.class, order.next());
put(SecurityContextPersistenceFilter.class, order.next());
put(HeaderWriterFilter.class, order.next());
... ...
private final Map<String, Integer> filterToOrder = new HashMap<>();
public void registerAfter(Class<? extends Filter> filter,
Class<? extends Filter> afterFilter) {
Integer position = getOrder(afterFilter);
if (position == null) {
throw new IllegalArgumentException(
"Cannot register after unregistered Filter " + afterFilter);
}
put(filter, position + 1);
}
RequestMatcher
用于判断request是否匹配,并返回匹配结果。
public interface RequestMatcher {
boolean matches(HttpServletRequest request);
default MatchResult matcher(HttpServletRequest request) {
boolean match = matches(request);
return new MatchResult(match, Collections.emptyMap());
}
class MatchResult {
private final boolean match;
private final Map<String, String> variables;
MatchResult(boolean match, Map<String, String> variables) {
this.match = match;
this.variables = variables;
}
}
}
默认实现了很多个RequestMatcher。
public final class AnyRequestMatcher implements RequestMatcher {
public static final RequestMatcher INSTANCE = new AnyRequestMatcher();
public boolean matches(HttpServletRequest request) {
return true;
}
}
public final class AndRequestMatcher implements RequestMatcher {
private final List<RequestMatcher> requestMatchers;
public AndRequestMatcher(List<RequestMatcher> requestMatchers) {
... ...
this.requestMatchers = requestMatchers;
}
public AndRequestMatcher(RequestMatcher... requestMatchers) {
this(Arrays.asList(requestMatchers));
}
public boolean matches(HttpServletRequest request) {
for (RequestMatcher matcher : requestMatchers) {
if (logger.isDebugEnabled()) {
logger.debug("Trying to match using " + matcher);
}
if (!matcher.matches(request)) {
logger.debug("Did not match");
return false;
}
}
return true;
}
}
构造函数
构造函数,保存了AuthenticationManagerBuilder实例,并保存了一些共用对象。
public HttpSecurity(ObjectPostProcessor<Object> objectPostProcessor,
AuthenticationManagerBuilder authenticationBuilder,
Map<Class<?>, Object> sharedObjects) {
super(objectPostProcessor);
Assert.notNull(authenticationBuilder, "authenticationBuilder cannot be null");
setSharedObject(AuthenticationManagerBuilder.class, authenticationBuilder);
for (Map.Entry<Class<?>, Object> entry : sharedObjects
.entrySet()) {
setSharedObject((Class<Object>) entry.getKey(), entry.getValue());
}
ApplicationContext context = (ApplicationContext) sharedObjects
.get(ApplicationContext.class);
this.requestMatcherConfigurer = new RequestMatcherConfigurer(context);
}
performBuild
@Override
protected DefaultSecurityFilterChain performBuild() {
//排序
filters.sort(comparator);
//构造DefaultSecurityFilterChain。会在每个configurer的configure()方法中,把filter加入到Filters
return new DefaultSecurityFilterChain(requestMatcher, filters);
}
Filters通过addFilter 添加。
public HttpSecurity addFilter(Filter filter) {
Class<? extends Filter> filterClass = filter.getClass();
if (!comparator.isRegistered(filterClass)) {
throw new IllegalArgumentException(
"The Filter class "
+ filterClass.getName()
+ " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");
}
this.filters.add(filter);
return this;
}
AuthenticationManagerBuilder配置。
为AuthenticationManagerBuilder 配置AuthenticationProvider ,UserDetailsService
public HttpSecurity authenticationProvider(
AuthenticationProvider authenticationProvider) {
getAuthenticationRegistry().authenticationProvider(authenticationProvider);
return this;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.security.config.annotation.web.HttpSecurityBuilder#userDetailsService
* (org.springframework.security.core.userdetails.UserDetailsService)
*/
public HttpSecurity userDetailsService(UserDetailsService userDetailsService)
throws Exception {
getAuthenticationRegistry().userDetailsService(userDetailsService);
return this;
}
private AuthenticationManagerBuilder getAuthenticationRegistry() {
return getSharedObject(AuthenticationManagerBuilder.class);
}