1. 简介
Spring Security中的所有功能都是通过过滤器来实现的,这些过滤器组成一个完整的过滤器链。过滤器链涉及很多基础组件,首先梳理一下这些关键组件,会方便理解Spring Security过滤器链。
2. ObjectPostProcessor
他是一个对象后置处理器,当一个对象创建成功后,如果需要一些额外的事情需要补充,就可以通过ObjectPostProcessor来进行处理。
在Spring Security中,开发者可以灵活的配置项目中需要哪些过滤器,一旦选定过滤器之后,每个过滤器会有一个对应的配置器,叫做xxxConfigurer(例如CorsConfigurer),过滤器都是在xxxConfigurer中new出来的,然后再postProcess方法中处理一遍,就将这些过滤器注入到Spring容器中了。
public interface ObjectPostProcessor<T> {
<O extends T> O postProcess(O object);
}
默认有两个继承类,继承关系如下
2.1 AutowireBeanFactoryObjectPostProcessor
当一个对象被new出来以后,只要调用AutowireBeanFactoryObjectPostProcessor#postProcess方法,就可以成功注入到Spring容器中。
@Override
@SuppressWarnings("unchecked")
public <T> T postProcess(T object) {
if (object == null) {
return null;
}
T result = null;
try {
result = (T) this.autowireBeanFactory.initializeBean(object, object.toString());
}
catch (RuntimeException ex) {
Class<?> type = object.getClass();
throw new RuntimeException("Could not postProcess " + object + " of type " + type, ex);
}
this.autowireBeanFactory.autowireBean(object);
if (result instanceof DisposableBean) {
this.disposableBeans.add((DisposableBean) result);
}
if (result instanceof SmartInitializingSingleton) {
this.smartSingletons.add((SmartInitializingSingleton) result);
}
return result;
}
2.2 CompositeObjectPostProcessor
他是一个组合的对象后置处理器,维护了一个List集合,存放了所有的后置处理器。在Spring Security框架中,最终使用的对象后置处理器其实就是CompositeObjectPostProcessor,他里面的集合默认只有一个对象,就是AutowireBeanFactoryObjectPostProcessor。
private static final class CompositeObjectPostProcessor implements ObjectPostProcessor<Object> {
private List<ObjectPostProcessor<?>> postProcessors = new ArrayList<>();
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public Object postProcess(Object object) {
for (ObjectPostProcessor opp : this.postProcessors) {
Class<?> oppClass = opp.getClass();
Class<?> oppType = GenericTypeResolver.resolveTypeArgument(oppClass, ObjectPostProcessor.class);
if (oppType == null || oppType.isAssignableFrom(object.getClass())) {
object = opp.postProcess(object);
}
}
return object;
}
}
3. SecurityFilterChain
SecurityFilterChain是Spring Security中的过滤器链对象
public interface SecurityFilterChain {
//用来判断request请求是否应该被当前过滤器链处理
boolean matches(HttpServletRequest request);
//如果matches返回true,那么request请求就会在getFilters方法返回的Filter集合中被处理
List<Filter> getFilters();
}
他的默认实现类是DefaultSecurityFilterChain,需要注意的点是,在一个Spring Security项目中,SecurityFilterChain实例可能有多个。
//省略部分代码
public final class DefaultSecurityFilterChain implements SecurityFilterChain {
private final RequestMatcher requestMatcher;
private final List<Filter> filters;
@Override
public List<Filter> getFilters() {
return this.filters;
}
@Override
public boolean matches(HttpServletRequest request) {
return this.requestMatcher.matches(request);
}
}
4. SecurityBuilder
Spring Security中很多对象都可以通过SecurityBuilder来构建,源码如下:
public interface SecurityBuilder<O> {
O build() throws Exception;
}
4.1 HttpSecurityBuilder
用来构建HttpSecurity对象,最终构建出来的对象为DefaultSecurityFilterChain,默认构建后的filter顺序如下:
HttpSecurityBuilder源码如下:
//HttpSecurityBuilder默认实现类只有HttpSecurity,可以把H当作HttpSecurity
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);
//配置认证器AuthenticationProvider
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);
//这个过滤器必须是Spring Security框架提供的过滤器的实例或者扩展,添加完成后,会自动进行排序
H addFilter(Filter filter);
}
4.2 AbstractSecurityBuilder
AbstractSecurityBuilder实现了SecurityBuilder接口,并对build做了完善,确保只build一次。
public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
private AtomicBoolean building = new AtomicBoolean();
private O object;
//设置为final,确保子类不会再重写这个方法
@Override
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;
}
protected abstract O doBuild() throws Exception;
}
4.3 AbstractConfiguredSecurityBuilder
它允许securityconfigururer被应用到它。这使得修改SecurityBuilder成为一种策略,它可以被自定义,并分解成许多securityconfigururer对象,这些对象比SecurityBuilder有更具体的目标。
例如,一个SecurityBuilder可以构建一个DelegatingFilterProxy,但是一个securityconfiger可以用会话管理、基于表单的登录、授权等所需的过滤器填充SecurityBuilder。
在这个类中有一个声明了一个枚举,用来描述构建过程的不同状态。
private static enum BuildState {
UNBUILT(0),
INITIALIZING(1),
CONFIGURING(2),
BUILDING(3),
BUILT(4);
private final int order;
private BuildState(int order) {
this.order = order;
}
public boolean isInitializing() {
return INITIALIZING.order == this.order;
}
public boolean isConfigured() {
return this.order >= CONFIGURING.order;
}
}
在AbstractConfiguredSecurityBuilder中与configurers相关的部分代码如下:
public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>> extends AbstractSecurityBuilder<O> {
private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers;
private final List<SecurityConfigurer<O, B>> configurersAddedInInitializing;
private final Map<Class<?>, Object> sharedObjects;
private final boolean allowConfigurersOfSameType;
private BuildState buildState;
private ObjectPostProcessor<Object> objectPostProcessor;
//向configures变量添加配置类,调用add方法
public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer) throws Exception {
configurer.addObjectPostProcessor(this.objectPostProcessor);
configurer.setBuilder(this);
this.add(configurer);
return configurer;
}
public <C extends SecurityConfigurer<O, B>> C apply(C configurer) throws Exception {
this.add(configurer);
return configurer;
}
//将所有的配置类保存到configures中,默认情况下,allowConfigurersOfSameType为false,所以List集合中的
//配置类始终只有一个
private <C extends SecurityConfigurer<O, B>> void add(C configurer) {
Assert.notNull(configurer, "configurer cannot be null");
Class<? extends SecurityConfigurer<O, B>> clazz = configurer.getClass();
synchronized(this.configurers) {
if (this.buildState.isConfigured()) {
throw new IllegalStateException("Cannot apply " + configurer + " to already built object");
} else {
List<SecurityConfigurer<O, B>> configs = null;
if (this.allowConfigurersOfSameType) {
configs = (List)this.configurers.get(clazz);
}
List<SecurityConfigurer<O, B>> configs = configs != null ? configs : new ArrayList(1);
((List)configs).add(configurer);
this.configurers.put(clazz, configs);
if (this.buildState.isInitializing()) {
this.configurersAddedInInitializing.add(configurer);
}
}
}
}
}
在AbstractConfiguredSecurityBuilder中与构建相关的部分代码如下:
//一边更新状态,一边执行构建方法
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;
}
}
protected void beforeInit() throws Exception {
}
protected void beforeConfigure() throws Exception {
}
protected abstract O performBuild() throws Exception;
//遍历所有配置类,并调用其init方法完成初始化操作
private void init() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.init((B) this);
}
for (SecurityConfigurer<O, B> configurer : this.configurersAddedInInitializing) {
configurer.init((B) this);
}
}
private void configure() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.configure((B) this);
}
}
4.4 ProviderManagerBuilder
ProviderManagerBuilder通过范型指定构建对象为AuthenticationManager
public interface ProviderManagerBuilder<B extends ProviderManagerBuilder<B>>
extends SecurityBuilder<AuthenticationManager> {
B authenticationProvider(AuthenticationProvider authenticationProvider);
}
4.5 AuthenticationManagerBuilder
AuthenticationManagerBuilder用来构建AuthenticationManager对象,他继承自AbstractConfiguredSecurityBuilder<AuthenticationManager, AuthenticationManagerBuilder>,并且实现了ProviderManagerBuilder<AuthenticationManagerBuilder>,部分代码如下
public class AuthenticationManagerBuilder extends AbstractConfiguredSecurityBuilder<AuthenticationManager, AuthenticationManagerBuilder> implements ProviderManagerBuilder<AuthenticationManagerBuilder> {
private AuthenticationManager parentAuthenticationManager;
private List<AuthenticationProvider> authenticationProviders = new ArrayList();
private UserDetailsService defaultUserDetailsService;
private Boolean eraseCredentials;
private AuthenticationEventPublisher eventPublisher;
//表示允许相同类型的配置类同时存在
public AuthenticationManagerBuilder(ObjectPostProcessor<Object> objectPostProcessor) {
super(objectPostProcessor, true);
}
public AuthenticationManagerBuilder parentAuthenticationManager(AuthenticationManager authenticationManager) {
if (authenticationManager instanceof ProviderManager) {
this.eraseCredentials(((ProviderManager)authenticationManager).isEraseCredentialsAfterAuthentication());
}
this.parentAuthenticationManager = authenticationManager;
return this;
}
public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) {
this.eraseCredentials = eraseCredentials;
return this;
}
//配置基于内存的数据源,会创建一个InMemoryUserDetailsManagerConfigurer配置类,并最终
//将该配置类添加到父类的configurers变量中,由于设置了允许相同类型的配置类同时存在
//因此该方法可以被调用多次
public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication() throws Exception {
return (InMemoryUserDetailsManagerConfigurer)this.apply(new InMemoryUserDetailsManagerConfigurer());
}
public JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcAuthentication() throws Exception {
return (JdbcUserDetailsManagerConfigurer)this.apply(new JdbcUserDetailsManagerConfigurer());
}
public <T extends UserDetailsService> DaoAuthenticationConfigurer<AuthenticationManagerBuilder, T> userDetailsService(T userDetailsService) throws Exception {
this.defaultUserDetailsService = userDetailsService;
return (DaoAuthenticationConfigurer)this.apply(new DaoAuthenticationConfigurer(userDetailsService));
}
public AuthenticationManagerBuilder authenticationProvider(AuthenticationProvider authenticationProvider) {
this.authenticationProviders.add(authenticationProvider);
return this;
}
//创建和配置AuthenticationManager的实现类ProviderManager
//ProviderManager创建成功后,会调用后置处理器处理一遍后再返回
protected ProviderManager performBuild() throws Exception {
if (!this.isConfigured()) {
this.logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null.");
return null;
} else {
ProviderManager providerManager = new ProviderManager(this.authenticationProviders, this.parentAuthenticationManager);
if (this.eraseCredentials != null) {
providerManager.setEraseCredentialsAfterAuthentication(this.eraseCredentials);
}
if (this.eventPublisher != null) {
providerManager.setAuthenticationEventPublisher(this.eventPublisher);
}
providerManager = (ProviderManager)this.postProcess(providerManager);
return providerManager;
}
}
private <C extends UserDetailsAwareConfigurer<AuthenticationManagerBuilder, ? extends UserDetailsService>> C apply(C configurer) throws Exception {
this.defaultUserDetailsService = configurer.getUserDetailsService();
return (UserDetailsAwareConfigurer)super.apply(configurer);
}
}
4.6 HttpSecurity
HttpSecurity的主要作用是用来构建一条过滤器链,也就是构建一个DefaultSecurityFilterChain对象。一个DefaultSecurityFilterChain对象包含一个路径匹配器和多个Spring Security过滤器,HttpSecurity中通过收集各种各样的xxxConfigurer,将Spring Security过滤器对应的配置类收集起来,并保存到父类AbstractConfiguredSecurityBuilder的configurers变量中。
在后续的构建过程中,再将这些xxxConfigurer构建为具体的Spring Security过滤器,并添加到HttpSecurity的filters对象中,部分代码如下
public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity> implements SecurityBuilder<DefaultSecurityFilterChain>, HttpSecurityBuilder<HttpSecurity> {
private final RequestMatcherConfigurer requestMatcherConfigurer;
private List<OrderedFilter> filters = new ArrayList();
private RequestMatcher requestMatcher;
private FilterOrderRegistration filterOrders;
private AuthenticationManager authenticationManager;
//以form表单登陆配置为例(别的大部分方法都很相似),有两种重载方法可以进行配置,第一种是一个无参formLogin
//方法,该方法返回一个FormLoginConfigurer<HttpSecurity>对象,开发者在该对象的基础上进行配置
public FormLoginConfigurer<HttpSecurity> formLogin() throws Exception {
return (FormLoginConfigurer)this.getOrApply(new FormLoginConfigurer());
}
//第二种是传入配置参数实例
public HttpSecurity formLogin(Customizer<FormLoginConfigurer<HttpSecurity>> formLoginCustomizer) throws Exception {
formLoginCustomizer.customize((FormLoginConfigurer)this.getOrApply(new FormLoginConfigurer()));
return this;
}
//传入authenticationProvider,最后在beforeConfigure方法中触发AuthenticationManager对象构建
public HttpSecurity authenticationProvider(AuthenticationProvider authenticationProvider) {
getAuthenticationRegistry().authenticationProvider(authenticationProvider);
return this;
}
//构建DefaultSecurityFilterChain,在此之前会对filters进行排序
protected DefaultSecurityFilterChain performBuild() {
ExpressionUrlAuthorizationConfigurer<?> expressionConfigurer = getConfigurer(
ExpressionUrlAuthorizationConfigurer.class);
AuthorizeHttpRequestsConfigurer<?> httpConfigurer = getConfigurer(AuthorizeHttpRequestsConfigurer.class);
boolean oneConfigurerPresent = expressionConfigurer == null ^ httpConfigurer == null;
Assert.state((expressionConfigurer == null && httpConfigurer == null) || oneConfigurerPresent,
"authorizeHttpRequests cannot be used in conjunction with authorizeRequests. Please select just one.");
this.filters.sort(OrderComparator.INSTANCE);
List<Filter> sortedFilters = new ArrayList<>(this.filters.size());
for (Filter filter : this.filters) {
sortedFilters.add(((OrderedFilter) filter).filter);
}
return new DefaultSecurityFilterChain(this.requestMatcher, sortedFilters);
}
}
4.7 WebSecurity
相比于HttpSecurity,WebSecurity在一个更大的层面上构建过滤器,WebSecurity负责将HttpSecurity所构建的DefaultSecurityFilterChain对象(可能有多个),以及其他一些需要忽略的请求,再次构建为一个FIlterChainProxy对象,同时添加上Http防火墙,部分核心代码如下:
public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements SecurityBuilder<Filter>, ApplicationContextAware, ServletContextAware {
private final List<SecurityBuilder<? extends SecurityFilterChain>> securityFilterChainBuilders = new ArrayList<>();
//保存所有被忽略的请求,不会经过spring security过滤器链
private final List<RequestMatcher> ignoredRequests = new ArrayList<>();
public WebSecurity addSecurityFilterChainBuilder(
SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder) {
this.securityFilterChainBuilders.add(securityFilterChainBuilder);
return this;
}
//在此处构建所有的securityFilterChains,然后将其作为参数构建filterChainProxy
protected Filter performBuild() throws Exception {
int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size();
List<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize);
List<RequestMatcherEntry<List<WebInvocationPrivilegeEvaluator>>> requestMatcherPrivilegeEvaluatorsEntries = new ArrayList<>();
for (RequestMatcher ignoredRequest : this.ignoredRequests) {
SecurityFilterChain securityFilterChain = new DefaultSecurityFilterChain(ignoredRequest);
securityFilterChains.add(securityFilterChain);
requestMatcherPrivilegeEvaluatorsEntries
.add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
}
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) {
SecurityFilterChain securityFilterChain = securityFilterChainBuilder.build();
securityFilterChains.add(securityFilterChain);
requestMatcherPrivilegeEvaluatorsEntries
.add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
}
if (this.privilegeEvaluator == null) {
this.privilegeEvaluator = new RequestMatcherDelegatingWebInvocationPrivilegeEvaluator(
requestMatcherPrivilegeEvaluatorsEntries);
}
FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
if (this.httpFirewall != null) {
filterChainProxy.setFirewall(this.httpFirewall);
}
if (this.requestRejectedHandler != null) {
filterChainProxy.setRequestRejectedHandler(this.requestRejectedHandler);
}
filterChainProxy.afterPropertiesSet();
Filter result = filterChainProxy;
if (this.debugEnabled) {
result = new DebugFilter(filterChainProxy);
}
this.postBuildAction.run();
return result;
}
}
FilterChainProxy就是我们最终构建出来的过滤器链,通过spring提供的DelegatingFilterProxy将FilterChainProxy对象嵌入到Web Filter中(原生过滤器链)
5. FilterChainProxy
如上图琐事,FilterChainProxy通过DelegatingFilterProxy代理过滤器被集成到Web Filter中,所以Spring Security中的最终执行的就是FilterChainProxy中的过滤器,部分代码如下:
public class FilterChainProxy extends GenericFilterBean {
private List<SecurityFilterChain> filterChains;
private FilterChainValidator filterChainValidator = new NullFilterChainValidator();
public FilterChainProxy(SecurityFilterChain chain) {
this(Arrays.asList(chain));
}
public FilterChainProxy(List<SecurityFilterChain> filterChains) {
this.filterChains = filterChains;
}
//doFilter方法相当于整个Spring Security过滤器链的入口
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
if (!clearContext) {
//进行实际的filter操作
doFilterInternal(request, response, chain);
return;
}
try {
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
doFilterInternal(request, response, chain);
}
catch (RequestRejectedException ex) {
this.requestRejectedHandler.handle((HttpServletRequest) request, (HttpServletResponse) response, ex);
}
finally {
SecurityContextHolder.clearContext();
request.removeAttribute(FILTER_APPLIED);
}
}
}
6. SecurityConfigurer
在这两个方法中对SecurityBuilder进行初始化和配置
public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {
void init(B builder) throws Exception;
void configure(B builder) throws Exception;
}