内容简介:本文是对 Spring Security Core 4.0.4 Release 进行源码分析的系列文章之一;本系列开始,将讲解有关 Spring Security 的配置相关的内容;本文为作者的原创作品,转载需注明出处;
本文是对 Spring Security Core 4.0.4 Release 进行源码分析的系列文章之一;
本系列开始,将讲解有关 Spring Security 的配置相关的内容;
本文为作者的原创作品,转载需注明出处;
简介
在《 Spring Security 源码分析九:Java config - WebSecurity & @EnableWebSecurity 》文中,笔者在HttpSecurity 小节中留了一个悬念,那就是通过 HttpSecurity 的 build() 方法将返回一个SecurityFilterChain 对象,SecurityFilterChain 对象由多个 Filter 所构成,组成了一条 Spring Security 的过滤链,但是并没有深入的去探讨 HttpSecurity 是如何去构建 SecurityFilterChain 对象的内部机制;本篇文章,笔者将试图去回答这个问题;
配置用例
先来看一些简单的用例,
单个 FilterChain 的配置
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
等价于做了如下的配置
<http>
<intercept-url pattern="/**" access="authenticated"/>
<form-login />
<http-basic />
</http>
- 每一个 and() 操作符就相当于 XML 配置中的一次换行,XML 配置中的每一行代表一个完整的配置;
-
配置 .authorizeRequests().anyRequest().authenticated() 相当于
<intercept-url pattern="/**" access="authenticated"/>
authorizeRequests()表示开始一个 <intercept-url> 配置节点的开始;
anyRequest()表示配置属性 pattern=”/**“;
authenticated()表示配置属性 access=”authenticated”;
上述的配置等价于配置了一个 SecurityFilterChain 对象,既是一个 Spring Security 安全链,因为没有指定安全链的起始链接,所以该安全链默认作用在 /** 访问 request 上的,并且使用默认实现的 form login 和 http basic authentication 对象;
多个 FilterChain 的配置
在 Spring Security 源码分析八:Spring Security 过滤链二 - Demo 例子 的例子中,通过 Java Config 的方式配置了两条不同的 Security Filter Chain;
首先,通过如下的方式配置了一条 /web/** 的安全过滤链,
http.antMatcher("/web/**") // the filter chain defined for web request
.authorizeRequests()
.antMatchers("/web/report/**").hasRole("MANAGER")
.anyRequest().authenticated()
.and()
.formLogin()
// login 的相对路径必须与 security chain 的的相对路径吻合,这里是 /web/**;注意 login 分两步,一步是 Getter 会到 login.html,另外一步是从 login.html -> post -> 6
// 允许访问
.permitAll();
再次,通过如下的方式配置了另一条 /rest/** 的安全过滤链,
http.antMatcher("/rest/**") // the filter chain defined for web request;
.csrf().disable() // rest 请求无需 CSRF Token;
.authorizeRequests()
.antMatchers("/rest/hello").hasRole("USER")
.anyRequest().authenticated()
.and()
.httpBasic();
上述的配置等价如下的配置,
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/web/**" filters="
securityContextPersistenceFilter,
logoutFilter,
usernamePasswordAuthenticationFilter,
exceptionTranslationFilter,
filterSecurityInterceptor">
<sec:intercept-url pattern="/web/report/**" access="ROLE_MANAGER"/>
</sec:filter-chain>
<sec:filter-chain pattern="/rest/**" filters="
securityContextPersistenceFilter,
logoutFilter,
basicAuthenticationFilter,
exceptionTranslationFilter,
filterSecurityInterceptor" >
<sec:intercept-url pattern="/rest/report/**" access="ROLE_USER"/>
</sec:filter-chain>
</sec:filter-chain-map>
</bean>
<!-- logout filter -->
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<!-- the post-logout destination -->
<constructor-arg value="/"/>
<constructor-arg>
<array>
<ref local="logoutHandler"/>
<!--高级配置 添加 rememberMe-->
<ref local="rememberMeServices"/>
</array>
</constructor-arg>
<property name="filterProcessesUrl" value="/logout"/>
</bean>
<bean id="basicAuthenticationFilter" ....>
......
</bean>
......
相关配置说明和其它配置元素
还是以上述单个 FilterChain 的配置为例
http -> HttpSecurity
Java Config 中的配置元素http等价于 XML 配置元素中的<http>;该实例既表示 HttpSecurity 实例本身;
and() : HttpSecurity
Java Config 中的配置元素and()等价于 XML 配置元素中的 换行 操作,也就表示准备要开始配置另外一个 Security 元素了;其实在 Java Config 的过程中,每一次的 and() 操作以后,返回的都是当前 HttpSecuirty 实例;可以看到,每一次相关方法的调用,比如、、返回的都是一个 SecurityConfigurer 对象,而通过调用 SecurityConfigurer.and() 返回的永远都是 SecurityBuilder 对象,这里对应的既是 HttpSecurity;
该部分将会在后面的部分有更详细的介绍;
antMatcher(String antPattern) : HttpSecurity
Java Config 中的配置元素antMatcher(antPattern)类似于进行如下的 XML 配置,
<sec:filter-chain pattern="/web/**" ... > .... </sec:filter-chain>
开启了一个新的 Security Chain 的配置;
authorizeRequests() : ExpressionUrlAuthorizationConfigurer
Java Config 中的配置元素authorizeRequests()等价于 XML 配置元素中的<intercept-url>操作,表示对特定 URL 执行的特定操作;这个方法比较有意思,返回的是 ExpressionUrlAuthorizationConfigurer<HttpSecurity>. ExpressionInterceptUrlRegistry 一个内嵌对象;该部分将会在后面的部分有更详细的介绍;
formLogin() : FormLoginConfigurer
Java Config 中的配置元素formLogin()等价于 XML 配置元素中的<form-login>操作,表示对特定 URL 执行的特定操作;该方法返回的是 FormLoginConfigurer 对象,该部分将会在后面的部分有更详细的介绍;
httpBasic() : HttpBasicConfigurer
Java Config 中的配置元素httpBasic()等价于 XML 配置元素中的<http-basic>操作;该方法返回的是 HttpBasicConfigurer 对象,该部分将会在后面的部分有更详细的介绍;
sessionManagement() : SessionManagementConfigurer
Java Config 中的配置元素sessionManagement()类似于进行如下的 XML 配置,
<session-management> <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" /> </session-management>
该方法返回的是 SessionManagementConfigurer 对象,该部分将会在后面的部分有更详细的介绍;
authenticationProvider( authenticationProvider ) : HttpSecurity
Java Config 中的配置元素authenticationProvider( authenticationProvider )类似于进行如下的 XML 配置,
<authentication-manager> <authentication-provider user-service-ref='myUserDetailsService'/> </authentication-manager>
该方法返回的是当前的 HttpSecurity 对象;
userDetailsService( userDetailsService ) : HttpSecurity
Java Config 中的配置元素userDetailsService()类似于进行如下的 XML 的配置,
<beans:bean id="myUserDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl"> <beans:property name="dataSource" ref="dataSource"/> </beans:bean>
portMapper() : PortMapperConfigurer
Java Config 中的配置元素portMapper()类似于进行如下的 XML 配置,
<port-mappings> <port-mapping http="9080" https="9443"/> </port-mappings>
exceptionHandling() : ExceptionHandlingConfigurer
Java Config 中的配置元素exceptionHandling()类似于进行如下的 XML 的配置,
<bean id="exceptionTranslationFilter" class="org.springframework.security.web .access.ExceptionTranslationFilter"> <property name="authenticationEntryPoint" ref="authenticationEntryPoint"/> <property name="accessDeniedHandler" ref="accessDeniedHandler"/> </bean> <bean id="authenticationEntryPoint" class="org.springframework.security.web .authentication.LoginUrlAuthenticationEntryPoint"> <property name="loginFormUrl" value="/login.do"/> </bean> <bean id="accessDeniedHandler" class="org.springframework.security.web .access.AccessDeniedHandlerImpl"> <property name="errorPage" value="/accessDenied.do"/> </bean>
从 ExceptionHandlingConfigurer 的配置方法 configure() 中也可以看到这个逻辑,
@Override
public void configure(H http) throws Exception {
AuthenticationEntryPoint entryPoint = getAuthenticationEntryPoint(http);
ExceptionTranslationFilter exceptionTranslationFilter = new ExceptionTranslationFilter(
entryPoint, getRequestCache(http));
if (accessDeniedHandler != null) {
exceptionTranslationFilter.setAccessDeniedHandler(accessDeniedHandler);
}
exceptionTranslationFilter = postProcess(exceptionTranslationFilter);
http.addFilter(exceptionTranslationFilter);
}
其它配置
如图,展示了 HttpSecuirty 所有相关的配置项,里面还包含 csrf() , logout() , anonymous() , requiresChannel() 等等非常重要的一系列的配置方法;
References
有关 XML 的配置参考 https://docs.spring.io/spring-security/site/docs/3.0.x/reference/ns-config.html
HttpSecurity
SecurityBuilder 的实体类总共有三个,HttpSecurity、WebSecurity 以及 AuthenticationManagerBuilder;下面笔者将逐个的分析每一个相关的类;
SecurityBuilder
SecurityBuilder 接口非常的简单,提供了一个 build() 方法,顾名思义,主要是用来执行构建操作的;
public interface SecurityBuilder<O> {
/**
* Builds the object and returns it or null.
*
* @return the Object to be built or null if the implementation allows it.
* @throws Exception if an error occurred when building the Object
*/
O build() throws Exception;
}
构建完成以后,将会返回对象 O;
AbstractSecurityBuilder
public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
private AtomicBoolean building = new AtomicBoolean();
private O object;
public final O build() throws Exception {
if (building.compareAndSet(false, true)) {
object = doBuild();
return object;
}
throw new AlreadyBuiltException("This object has already been built");
}
/**
* @return the Object that was built
*/
public final O getObject() {
if (!building.get()) {
throw new IllegalStateException("This object has not been built");
}
return object;
}
protected abstract O doBuild() throws Exception;
}
三个方法,
-
build()
执行构建动作,通过调用抽象方法 build() 完成构建;
-
getObject()
获得构建成功以后的对象;
-
doBuild()
抽象方法,供子类实现其构建方法;
AbstractConfiguredSecurityBuilder
该抽象类中的逻辑非常的关键了,将其核心关键代码摘要如下,
public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>
extends AbstractSecurityBuilder<O> {
......
@SuppressWarnings("unchecked")
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;
}
......
/**
* Sets an object that is shared by multiple {@link SecurityConfigurer}.
*
* @param sharedType the Class to key the shared object by.
* @param object the Object to store
*/
@SuppressWarnings("unchecked")
public <C> void setSharedObject(Class<C> sharedType, C object) {
this.sharedObjects.put((Class<Object>) sharedType, object);
}
@SuppressWarnings("unchecked")
public <C> C getSharedObject(Class<C> sharedType) {
return (C) this.sharedObjects.get(sharedType);
}
......
@SuppressWarnings("unchecked")
private <C extends SecurityConfigurer<O, B>> void add(C configurer) throws Exception {
Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer.getClass();
synchronized (configurers) {
....
List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers.get(clazz) : null;
....
configs.add(configurer);
this.configurers.put(clazz, configs);
....
}
}
......
@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;
}
}
......
/**
* Subclasses must implement this method to build the object that is being returned.
*
* @return
*/
protected abstract O performBuild() throws Exception;
@SuppressWarnings("unchecked")
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 : configurersAddedInInitializing) {
configurer.init((B) this);
}
}
@SuppressWarnings("unchecked")
private void configure() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.configure((B) this);
}
}
}
好些个核心的方法,下面我们一个一个的来屡吧,
-
apply(C configurer)
这里笔者罗列了两个 apply(C configurer) 方法,目的是为了描述一个调试的 bug,HttpSecurity 的 getOrApply(configurer) 方法,
@SuppressWarnings("unchecked") private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> C getOrApply( C configurer) throws Exception { C existingConfig = (C) getConfigurer(configurer.getClass()); if (existingConfig != null) { return existingConfig; } return apply(configurer); }如果通过 COMMAND + 鼠标左键点击 apply(configurer) 跳转到的是上述的方法
public <C extends SecurityConfigurer<O, B>> C apply(C configurer) throws Exception { add(configurer); return configurer; }如果是这样的话,就有一个疑问了,那就是如果通过 configurer.and() 方法获得 HttpSecurity 既是上述的 Build 对象 B ,比如通过 http.csrf().and() 就无法获取 HttpSecurity 对象了,自然也就没有办法继续进行 HttpSecurity 的相关配置了;不过,经过笔者的调试过程中发现,实际上,经过 HttpSecurity.getOrApply(configurer) 方法调用的其实是
@SuppressWarnings("unchecked") public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer) throws Exception { configurer.addObjectPostProcessor(objectPostProcessor); configurer.setBuilder((B) this); add(configurer); return configurer; }该方法中,通过
configurer.setBuilder((B) this)的方式将 HttpSecurity 赋值给了当前的 configurer,所以自然也就可以通过该 configurer 获取到当前的 HttpSecurity 对象了;Debug 过程的截图如下,可见,调用的正式上述方法; -
add(C configurer)
该方法在 apply(C configurer) 方法中被调用,目的是将 configurer 添加到 builder 的 configurers 中;唯一需要注意的是,configurers 是一个以 configurer class 为
主键的 Map,其值存储的就是按照 class 分类号的 configurers;为什么这样设计?难不成同一个类型的 configurer class 还会有多个 configurers?笔者暂时还没有想到相应的场景; -
setSharedObject(Class
sharedType, C object)
当需要覆盖掉 configurer 的一些 工具 累的时候,可以使用这个方法;
-
doBuild():O
该方法是核心中的核心,执行构建完以后,将返回构建好的对象;笔者在前面分析 WebSecurity 的构建过程 中比较详细的描述了 WebSecurity 的三步构造过程,init、configure 以及 perform build 步骤;现在,我们再从源码的层面,依次看下这三个方法所执行的逻辑,-
init build process
对应前三行代码,
buildState = BuildState.INITIALIZING; beforeInit(); init();
首先,执行 beforeInit() 方法,对应执行的是一个模板方法,子类需要继承并实现该方法来实现一些初始化之前的方法;如下所述,
/** * Invoked prior to invoking each {@link SecurityConfigurer#init(SecurityBuilder)} * method. Subclasses may override this method to hook into the lifecycle without * using a {@link SecurityConfigurer}. */ protected void beforeInit() throws Exception { }再次,执行 init() 方法,
@SuppressWarnings("unchecked") private void init() throws Exception { Collection<SecurityConfigurer<O, B>> configurers = getConfigurers(); for (SecurityConfigurer<O, B> configurer : configurers) { configurer.init((B) this); } .... }可以看到,在初始化构建过程当中,会首先依次执行各个 configurer 的 init() 方法;
-
configure build process
这里的逻辑与 init build process 大同小异,同样是先执行模板方法 beforeConfigurer() 方法,需要子类继承实现;然后再依次遍历 configurer 并执行其 configurer() 方法;
-
perform build process
这个过程执行抽象方法 performBuild(),该方法必须由子类实现;也就是说,三个子类 HttpSecurity、WebSecurity 以及 AuthenticationManagerBuilder 都有实现这个方法,这里,我们看看 HttpSecurity 的实现,
@Override protected DefaultSecurityFilterChain performBuild() throws Exception { Collections.sort(filters, comparitor); return new DefaultSecurityFilterChain(requestMatcher, filters); }首先,根据 filters 的优先级排好序,然后通过构造好的 requestMatcher 和 filters 来初始化一个 DefaultSecurityFilterChain 对象并返回;
-
-
init()
由 doBuild() 方法的 init build process 所调用;
-
configure()
由 doBuild() 方法的 configure build process 所调用;
HttpSecurity
由可知,HttpSecurity 是一个 SecurityBuilder 实例,通过其父类AbstractConfiguredSecurityBuilderdoBuild() 方法的三步构建 init、configure 以及 perform build 最终返回一个 SecurityFilterChain 实例;可见,HttpSecurity 的职责就是通过一系列的 configurer 并且通过三步构建步骤最后生成一个 SecurityFilterChain 实例,该实例最终由 FilterChainProxy 加载;更多有关 HttpSecurity 构建的过程参考HttpSecurity.build 部分内容;
从HttpSecurity 相关配置元素和操作中,可以知道,HttpSecurity 通过各种配置方法注入了不同的 configurers,既对象,并且通过 getOrApply(configurer) 方法将 configurer 注入到父类的configurers队列中(注意是个 Map 对象),
@SuppressWarnings("unchecked")
private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> C getOrApply(
C configurer) throws Exception {
C existingConfig = (C) getConfigurer(configurer.getClass());
if (existingConfig != null) {
return existingConfig;
}
return apply(configurer);
}
更多有关此部分的内容参考AbstractConfiguredSecurityBuilder中 apply(C configurer) 小节;另外这里 apply(configurer) 调用的是父类的第一个 apply(C configurer); 注意 ,正是因为在 apply 的过程中,将当前的 builder 既 HttpSecurity 对象注入到了 configurer 中,所以,可以通过任意的一个 configurer 对象通过调用其 and() 方法都可以获取到当前的 HttpSecurity 对象;就类似于在配置过程中通过 http.csrf().and() 既可以获取得到 HttpSecurity 对象;
Ok,通过上述分析,我们可以知道,HttpSecurity 通过若干 SecurityConfigurer 配置,通过其 configure() 方法,创建了若干个 Filters,正是这些 Filters 构成了 HttpSecurity 的核心,也正是这些 Filters 构建了 SecurityFilterChain 对象;那么,下面,我们就来一睹的风采;
SecurityConfigurer
由类图可知,SecurityConfigurer 主要分为两大类,WebSecurityConfigurer 和 SecurityConfigureAdapter;
注意,这里有一个关键的行为区别,那就是,WebSecurityConfigurerAdapter 类型的配置类,比如 WebConfigSecurity 和 RestConfigSecurity 不包含与之关联的 SecurityBuilder 实例,这里指的是 WebSecurity;而 SecurityConfigurerAdapter 类型的相关配置类则相反,均包含与其关联的 SecurityBuilder 类型实例,比如 AuthenticationManagerBuilder 以及 HttpSecurity,且是一对一的关系,这也就是为什么通过 SecurityConfigurerAdapter. and() 方法可以获取与之关联的 SecurityBuilder 的根本原因;
WebSecurityConfigurer
该部分参考 WebSecurity 章节的相关内容 WebSecurityConfigurer 的介绍;WebSecurityConfigurer 的主要职责就是扩展出用户自定义的有关 HttpSecurity 的配置;
SecurityConfigurerAdapter
由上述类图可知,包含三个子类,不过这里,笔者主要针对 UserDetailsAwareConfigurer 和 AbstractHttpConfigurer 来进行讲解;并且重要的是,该类提供了两个比较重要的方法;
-
and()
该方法将会始终返回 HttpSecurity 对象;
-
getBuilder()
and() 方法改回调用此方法来获取 Builder 对象,既 HttpSecurity 对象;
AbstractHttpConfigurer
由此类扩展出了多个与 HttpSecurity 相关联的 configurers,比如 HttpBasicConfigurer、FormLoginConfigurer 以及 ExpressionUrlAuthorizationConfigurer;
再来看一下,关注点聚焦到 HttpSecurity 上;
从HttpSecurity.build 的介绍可知 HttpSecurity 的构建的目的就是生成 Filters,然后将这些 Filters 作为构造参数初始化 DefaultSecurityFilterChain 对象并返回;而过程中,Filters 的生成就与 configurers 的方法 configure() 息息相关了;下面,笔者就相关的方法介绍如下,
HttpBasicConfigurer.configure(B http)
参数 B 指的是泛型 Builder,这里既是 HttpSecurity;
@Override
public void configure(B http) throws Exception {
AuthenticationManager authenticationManager = http
.getSharedObject(AuthenticationManager.class);
BasicAuthenticationFilter basicAuthenticationFilter = new BasicAuthenticationFilter(
authenticationManager, authenticationEntryPoint);
if (authenticationDetailsSource != null) {
basicAuthenticationFilter
.setAuthenticationDetailsSource(authenticationDetailsSource);
}
RememberMeServices rememberMeServices = http.getSharedObject(RememberMeServices.class);
if(rememberMeServices != null) {
basicAuthenticationFilter.setRememberMeServices(rememberMeServices);
}
basicAuthenticationFilter = postProcess(basicAuthenticationFilter);
http.addFilter(basicAuthenticationFilter);
}
下面笔者就 HttpBasicConfigurer 的配置的过程做进行详细的分析,
SharedObject Filter
ExpressionUrlAuthorizationConfigurer
该对象的 configure 方法在其父类 AbstractInterceptUrlConfigurer 中,
@Override
public void configure(H http) throws Exception {
FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http);
if (metadataSource == null) {
return;
}
FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(
http, metadataSource, http.getSharedObject(AuthenticationManager.class));
if (filterSecurityInterceptorOncePerRequest != null) {
securityInterceptor
.setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest);
}
securityInterceptor = postProcess(securityInterceptor);
http.addFilter(securityInterceptor);
http.setSharedObject(FilterSecurityInterceptor.class, securityInterceptor);
}
可见,目的正是为了生成一个 FilterSecurityInterceptor 既 Filter 对象,并将其载入到 HttpSecurity 对象中;
FormLoginConfigurer
同样,该对象的 configure 方法也是在其父类 AbstractAuthenticationFilterConfigurer 中;
@Override
public void configure(B http) throws Exception {
PortMapper portMapper = http.getSharedObject(PortMapper.class);
if (portMapper != null) {
authenticationEntryPoint.setPortMapper(portMapper);
}
authFilter.setAuthenticationManager(http
.getSharedObject(AuthenticationManager.class));
authFilter.setAuthenticationSuccessHandler(successHandler);
authFilter.setAuthenticationFailureHandler(failureHandler);
if (authenticationDetailsSource != null) {
authFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
}
SessionAuthenticationStrategy sessionAuthenticationStrategy = http
.getSharedObject(SessionAuthenticationStrategy.class);
if (sessionAuthenticationStrategy != null) {
authFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);
}
RememberMeServices rememberMeServices = http
.getSharedObject(RememberMeServices.class);
if (rememberMeServices != null) {
authFilter.setRememberMeServices(rememberMeServices);
}
F filter = postProcess(authFilter);
http.addFilter(filter);
}
上面代码的核心在 authFilter,而该 authFilter 正是 UsernamePasswordAuthenticationFilter,该 authFilter 的初始化过程在 FormLoginConfigurer 的构造函数中,
public FormLoginConfigurer() {
super(new UsernamePasswordAuthenticationFilter(), null);
usernameParameter("username");
passwordParameter("password");
}
UserDetailsAwareConfigurer
UserDetailsAwareConfigurer 主要涉及两个实体类 InMemoryUserDetailsManagerConfigurer 和 JdbcUserDetailsManagerConfigurer ;顾名思义,这两个类都是对用户身份信息进行验证的类;如类图中所示,这两个 configurers 将会作为 AuthenticationManagerBuilder 的 configures 来进行构建,最终构建的结果是返回一个 ProviderManager 对象;有关这部分内容笔者将会在下一章节对其进行描述;
总结
正如对 WebSecurity 的总结 那样,WebSecurity 与 HttpSecurity 的关系是一对多的关系,也就是说,HttpSecurity 正是为 Spring Security 构建多个安全链 SecurityFilterChain 的核心类;WebSecurity 将构建出 FilterChainProxy, FilterChainProxy 包含多个 SecurityFilterChain 既安全链;
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 以太坊源码分析(36)ethdb源码分析
- [源码分析] kubelet源码分析(一)之 NewKubeletCommand
- libmodbus源码分析(3)从机(服务端)功能源码分析
- [源码分析] nfs-client-provisioner源码分析
- [源码分析] kubelet源码分析(三)之 Pod的创建
- Spring事务源码分析专题(一)JdbcTemplate使用及源码分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Web Designer's Idea Book
Patrick Mcneil / How / 2008-10-6 / USD 25.00
The Web Designer's Idea Book includes more than 700 websites arranged thematically, so you can find inspiration for layout, color, style and more. Author Patrick McNeil has cataloged more than 5,000 s......一起来看看 《The Web Designer's Idea Book》 这本书的介绍吧!