Spring Security源码解析(二.创建FilterChainProxy)

上一章介绍了Spring Security的相关知识点,这章将详细分析源码。

首先需要认识到Spring Security的关键是filter——FilterChainProxy,经过一层层的filter才能最终访问到我们的资源信息。

同时要了解,访问不同的uri,系统会采取对应的filter列表进行过滤,如下图所示。

严谨点说不止是uri,可以自定义匹配头信息啊或者其他的,http请求中可以用来区分的都可以做为匹配条件。这里为了方便理解。

那么Spring Security启动的时候是如何加载这些filter和排序的呢?下面是访问/login uri对应的FilterChain。

                                          

Spring Security filter配置与原理

上一章我们了解到,需要人为配置WebSecurityConfigurerAdapter的继承类,如下图所示。注意到类上有注解@EnableWebSecurity。

@Configuration
   @EnableWebSecurity
   public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
  
   	@Override
   	public void configure(WebSecurity web) throws Exception {
   		web.ignoring()
   		// Spring Security should completely ignore URLs starting with /resources/
   				.antMatchers("/resources/**");
   	}
  
   	@Override
   	protected void configure(HttpSecurity http) throws Exception {
   		http.authorizeRequests().antMatchers("/public/**").permitAll().anyRequest()
   				.hasRole("USER").and()
   				// Possibly more configuration ...
   				.formLogin() // enable form based log in
   				// set permitAll for all URLs associated with Form Login
   				.permitAll();
   	}
  
   	@Override
   	protected void configure(AuthenticationManagerBuilder auth) {
   		auth
   		// enable in memory based authentication with a user named "user" and "admin"
   		.inMemoryAuthentication().withUser("user").password("password").roles("USER")
   				.and().withUser("admin").password("password").roles("USER", "ADMIN");
   	}
  
   	// Possibly more overridden methods ...
   }

@EnableWebSecurity是用于初始化WebSecurityConfiguration.class和引入@EnableGloabalAuthentication等,源码如下。

@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class,
		SpringWebMvcImportSelector.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;
}

为何要加载WebSecurityConfiguration呢?它又有什么用呢?在此之前先得了解几个概念。

SecurityBuilder<O>

顾名思义是一个builder构造器,创建并返回一个类型为O的对象,源码如下

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;
}

它的实现类如下图所示,可以看到很多熟悉的类。

                               

AbstractSecurityBuilder<O>核心方法有

  • build()
  • doBuild()
  • getObject()

源码如下,AtomicBoolean.compareAndSet(false,true)限定build()只会进行一次!然后子类需要重写的方法变为doBuild()。

public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
	private AtomicBoolean building = new AtomicBoolean();

	private O object;

	// 只会创建一次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");
	}

	// 获取object
	public final O getObject() {
		if (!this.building.get()) {
			throw new IllegalStateException("This object has not been built");
		}
		return this.object;
	}

	// 子类需要继承doBuild()方法
	protected abstract O doBuild() throws Exception;
}

AbstractConfiguredSecurityBuilder<O,B extends SecurityBuilder<O>>  主要作用是将SpringConfigurer注入到属性configurers中,然后重写doBuild()方法遍历configurers进行init()和configure()。

它的子类HttpSecurity和WebSecurity都沿用了它的doBuild()方法!!!即遍历configures进行init()和configure()!!!

核心方法

  • apply(C configurer)
  • add(C configurer)
  • doBuild()
  • abstract performBuild()

核心属性(WebSecurity,HttpSecurity都会沿用该重要属性)

private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers = new LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>>();

configurers是个LinkedHashMap,key为class,value为List<SecurityConfigurer<O,B>>,通过apply()方法将configure存入configures中。

public <C extends SecurityConfigurer<O, B>> C apply(C configurer) throws Exception {
		add(configurer);
		return configurer;
	}


@SuppressWarnings("unchecked")
	private <C extends SecurityConfigurer<O, B>> void add(C configurer) throws Exception {
		Assert.notNull(configurer, "configurer cannot be null");

		Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer
				.getClass();
		synchronized (configurers) {
            // buildState是个enum类,有几个状态如UNBUILT,INITIALIZING,CONFIGURING,BUILDING,BUILT
			if (buildState.isConfigured()) {
				throw new IllegalStateException("Cannot apply " + configurer
						+ " to already built object");
			}
			List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers
					.get(clazz) : null;
			if (configs == null) {
				configs = new ArrayList<SecurityConfigurer<O, B>>(1);
			}
			configs.add(configurer);
            // put进configurers中
			this.configurers.put(clazz, configs);
			if (buildState.isInitializing()) {
				this.configurersAddedInInitializing.add(configurer);
			}
		}
	}

既然apply()方法将SecurityConfigurer注入了属性configurers中,肯定要用到该属性,下面就是核心代码doBuild()

    // 重写了AbstractSecurityBuilder方法
    @Override
	protected final O doBuild() throws Exception {
		synchronized (configurers) {
                    // 状态=1
			buildState = BuildState.INITIALIZING;

			beforeInit();
                    // 遍历configurers中所有configurer,分别执行init()创建SecurityBuilder<O>
			init();

			buildState = BuildState.CONFIGURING;

			beforeConfigure();
                    // 遍历后执行各个实现类的configure()方法
			configure();

			buildState = BuildState.BUILDING;

                    // abstract方法,获取build后的值
			O result = performBuild();

			buildState = BuildState.BUILT;

			return result;
		}
	}

SecurityConfigurer<O,B extends SecurityBuilder<O>>

一句话概括:初始化(init)SecurityBuilder,且配置(configure)SecurityBuilder

/**
* 初始化B,且配置B的相关属性
* B SecurityBuilder<O>的子类
* O B.build()返回的object类型
*/
public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {
	/**
     * 初始化SecurityBuilder<O>	
     * 只创建设置了共享的变量,不会设置configure()中需要的特殊属性
	 * @param builder
	 * @throws Exception
	 */
	void init(B builder) throws Exception;

	/**
	 * 设置SecurityBuilder<O>的特殊属性
     * 如
	 */
	void configure(B builder) throws Exception;
}

SecurityConfigurer<O,B extends SecurityBuilder<O>>的实现类见下图,终于见到了我们的老朋友WebSecurityConfigurerAdapter

                                         

WebSecurityConfigurer是继承了SecurityConfigurer的接口,SecurityBuilder返回类型是Filter!!!

public interface WebSecurityConfigurer<T extends SecurityBuilder<Filter>> extends
		SecurityConfigurer<Filter, T> {

}

WebSecurityConfigurerAdapter

对应的SecurityBuilder是WebSecurity(继承SecurityBuilder<Filter>),里面有方法init(WebSecurity web)和configure(WebSecurity Web)。三大configure()还记得么?

configure(AuthenticationManagerBuilder auth) 
configure(HttpSecurity http)
configure(WebSecurity web)

如果不记得的话可以移步到上一章进行查阅。今天主要探讨下WebSecurityConfigurerAdapter作为SecuityBuilder<Filter>和SecurityConfigurer<Filter,T>的功能。

SecurityConfigurer的继承类自然需要init()和configure()。

其中init()的作用是获取HttpSecurity,并将http作为SecurityBuilder<? extends SecurityFilterChain> 存入webSecurity.SecurityFilterChainBuilders属性中。httpSecurity包含configurers属性(如ExceptionHandlingConfigurer、),通过http.csrf().and()来设置configurer,后期这些configurers进行configure时会将特定的filter加入到httpSecurity中。

下图是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);
	}

下图是WebSecurityConfigurerAdapter中的部分源码

 

 

 

@Order(100)
public abstract class WebSecurityConfigurerAdapter implements
		WebSecurityConfigurer<WebSecurity> {


/**
*  AbstractConfiguredSecurityBuilder(实现类有WebSecurity,HttpSecurity等)中的init()
*  会遍历所有configurers,调用configure.init()方法,那么WebSecurityConfigurerAdapter作为
*  configure调用的init()方法就是下面的代码
*  获取HttpSecurity,存入webSecurity中
*/
public void init(final WebSecurity web) throws Exception {
		final HttpSecurity http = getHttp();
		web.addSecurityFilterChainBuilder(http).postBuildAction(new Runnable() {
			public void run() {
				FilterSecurityInterceptor securityInterceptor = http
						.getSharedObject(FilterSecurityInterceptor.class);
				web.securityInterceptor(securityInterceptor);
			}
		});
	}



/**
* 获取HttpSecurity实例,configure(http)后,http中的属性configurers注入相应的configurer
* http.csrf()会将CsrfConfigurer<HttpSecurity>存入HttpSecurity.configurers中
* http.csrf().disable()从HttpSecurity.configurers中移除CsrfConfigurer
* 依次类推
*/
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);
		if (!disableDefaults) {
			// @formatter:off
            // headers()等方法将configure apply()到了http的属性configurers中,这里默认会注入10个configurer
			http
				.csrf().and()
				.addFilter(new WebAsyncManagerIntegrationFilter())
				.exceptionHandling().and()
				.headers().and()
				.sessionManagement().and()
				.securityContext().and()
				.requestCache().and()
				.anonymous().and()
				.servletApi().and()
				.apply(new DefaultLoginPageConfigurer<HttpSecurity>()).and()
				.logout();
			// @formatter:on
			ClassLoader classLoader = this.context.getClassLoader();
                // 默认是为空
			List<AbstractHttpConfigurer> defaultHttpConfigurers =
					SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);

			for(AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
				http.apply(configurer);
			}
		}
        // this.configurer(http)  根据this的实现类选择对应方法
		configure(http);
		return http;
	}
}

SecurityFilterChain

定义一个Filter Chain,包含一组Filters,且提供方法判断与request的路由是否匹配,源码如下。

public interface SecurityFilterChain {

	boolean matches(HttpServletRequest request);

	List<Filter> getFilters();
}

SecurityFilterChain常用于SecurityBuilder<? extends SecurityFilterChain>,作为builder的返回类型,通过build()获取到实例后,存入FilterChainProxy的属性List<SecurityFilterChain> filterChains中,在FilterChainProxy.doFilterInternal()中执行getFilters(HttpServletRequest request),找出对应request的SecurityFilterChain并返回Filters。

继承类为DefaultSecurityFilterChain,有属性RequestMatcher requestMatcher和List<Filter> filters

FilterChainProxy

非常重要的知识点!!!

filter chain代理,由Spring管理生命周期。

在Spring Security框架中,用户想要访问资源需要经过FilterChainProxy(本质上是个Filter)来过滤。

里面包含一组SecuriyFilterChains,每个uri都对应一个SecurityFilterChain,即对应SecurityFilterChain中的Filters

核心代码如下

// 继承了Filter
public class FilterChainProxy extends GenericFilterBean {

    // 重要属性,由WebSecurity中的performBuild()方法传递值过来
	private List<SecurityFilterChain> filterChains;

	private FilterChainValidator filterChainValidator = new NullFilterChainValidator();


	public FilterChainProxy() {
	}

	public FilterChainProxy(SecurityFilterChain chain) {
		this(Arrays.asList(chain));
	}

	public FilterChainProxy(List<SecurityFilterChain> filterChains) {
		this.filterChains = filterChains;
	}

	
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
		if (clearContext) {
			try {
				request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
                  // 跳转到doFilterInternal方法
				doFilterInternal(request, response, chain);
			}
			finally {
				SecurityContextHolder.clearContext();
				request.removeAttribute(FILTER_APPLIED);
			}
		}
		else {
			doFilterInternal(request, response, chain);
		}
	}

	private void doFilterInternal(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		FirewalledRequest fwRequest = firewall
				.getFirewalledRequest((HttpServletRequest) request);
		HttpServletResponse fwResponse = firewall
				.getFirewalledResponse((HttpServletResponse) response);
          // 根据request,SecurityFilterChains获取符合路由规则的SecurityFilterChain,并提取出filters
		List<Filter> filters = getFilters(fwRequest);

		if (filters == null || filters.size() == 0) {
			if (logger.isDebugEnabled()) {
				logger.debug(UrlUtils.buildRequestUrl(fwRequest)
						+ (filters == null ? " has no matching filters"
								: " has an empty filter list"));
			}

			fwRequest.reset();

			chain.doFilter(fwRequest, fwResponse);

			return;
		}
           // 虚拟filter chain,这是个内部类,模拟doFilter的动作
		VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);
		vfc.doFilter(fwRequest, fwResponse);
	}

         // 返回第一个满足路由规则的SecurityFilterChain
         private List<Filter> getFilters(HttpServletRequest request) {
		for (SecurityFilterChain chain : filterChains) {
			if (chain.matches(request)) {
				return chain.getFilters();
			}
		}

		return null;
	}
}

WebSecurity

重头戏来了,前面介绍的所有知识点都是为了给它铺路,简单概括就是

本质是SecurityBuilder<Filter>

有重要属性List<SecurityBuilder<? extends SecurityFilterChains>> securityFilterChainsBuilder,默认值是由WebSecurityConfigurerApdapter中传入的HttpSecurity。

继承了抽象类AbstractConfiguredSecurityBuilder(Filter,WebSecurity),重写抽象方法performBuild(),创建FilterChainProxy(Filter的实现类)并返回

ignoring()方法排除无需认证的路径

public final class WebSecurity extends
		AbstractConfiguredSecurityBuilder<Filter, WebSecurity> 
implements
		SecurityBuilder<Filter>, ApplicationContextAware {
private final List<SecurityBuilder<? extends SecurityFilterChain>> securityFilterChainBuilders = new ArrayList<SecurityBuilder<? extends SecurityFilterChain>>();

    
/**
*   添加securityFilterChainBuilder
*   默认WebSecurityConfigurerAdapter中的init(WebSecurity web)方法会调用这个方法
*   传入的securityFilterChainBuilder是getHttp()返回的HttpSecurity
*   securityFilterChainBuilder 是SecurityBuilder.build()返回SecurityFilterChain
*   SecurityFilterChain 有getFilters()和matches()方法
*/
public WebSecurity addSecurityFilterChainBuilder(
			SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder) {
		this.securityFilterChainBuilders.add(securityFilterChainBuilder);
		return this;
}  


     /**
     * 返回类型是FilterChainProxy
     * 从securityFilterChainBuilders中遍历securityFilterChainBuilder,将build()的返回值SecurityFilterChain写入集合securityFilterChains中
     * 将securityFilterChains注入到新建的FilterChainProxy里,FilterChainProxy.doFilterInternal()方法会从securityFilterChains中
     * 选取与request匹配的SecurityFilterChain,提取其中的filters作为filter chain
     */
    @Override
	protected Filter performBuild() throws Exception {
		
		int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
		List<SecurityFilterChain> securityFilterChains = new ArrayList<SecurityFilterChain>(
				chainSize);
		for (RequestMatcher ignoredRequest : ignoredRequests) {
			securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
		}
		for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
			securityFilterChains.add(securityFilterChainBuilder.build());
		}
          // 传入securityFilterChains初始化filterChainProxy,主要方法doFilterInternal()
		FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
		if (httpFirewall != null) {
			filterChainProxy.setFirewall(httpFirewall);
		}
		filterChainProxy.afterPropertiesSet();

		Filter result = filterChainProxy;
		
		postBuildAction.run();
		return result;
	}
}

HttpSecurity

本质是SecurityBuilder<DefaultSecurityFilterChain>,可以传入到WebSecurity的securityFilterChainBuilders属性中

属性 List<Filter> filters     方法  addFilter(),addFilterAt()等

一般在WebSecurityConfigurerApdater的继承类中使用

@Configuration
	   @EnableWebSecurity
	   public class AuthorizeUrlsSecurityConfig extends WebSecurityConfigurerAdapter {
	  
	   	@Override
	   	protected void configure(HttpSecurity http) throws Exception {
	   		http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin();
	   	}
	  
	   	@Override
	   	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
	   		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
	   				.and().withUser("adminr").password("password").roles("ADMIN", "USER");
	   	}
	   }

WebSecurityConfiguration

主要作用是初始化WebSecurity,且创建名为“springSecurityFilterChain”类型为FilterChainProxy的过滤器。

核心方法有

  • setFilterChainProxySecurityConfigurer
  • springSecurityFilterChain()

setFilterChainProxySecurityConfigurer创建webSecurity,并通过apply(Configurer c)方法注入spring容器管理的所有WebSecurityConfigurer。

/**
* spring注入SecurityConfigurer<FilterChainProxy,WebSecurity>
* webSecurityConfigurers 默认为3个,
*/
@Autowired(required = false)
public void setFilterChainProxySecurityConfigurer(
			ObjectPostProcessor<Object> objectPostProcessor,
			@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
			throws Exception {
                // 新建webSecurity,然后apply() configurers
		webSecurity = objectPostProcessor
				.postProcess(new WebSecurity(objectPostProcessor));
		
        ...
		
        // 
        for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
			webSecurity.apply(webSecurityConfigurer);
		}
		this.webSecurityConfigurers = webSecurityConfigurers;
	}

根据@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") 定位到下图所示的方法,从beanFactory里获取所有类型为WebSecurityConfigurer的实例,这里有3个,其中securityConfig是自己编写继承WebSecurityConfigurerAdapter的类。

springSecurityFilterChain()通过webSecurity.build()方法创建名为"springSecurityFilterChain"的FilterChainProxy

@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
	public Filter springSecurityFilterChain() throws Exception {
           // 先执行了setFilterChainProxySecurityConfigurer()方法,所以属性webSecurityConfigurers有值
		boolean hasConfigurers = webSecurityConfigurers != null
				&& !webSecurityConfigurers.isEmpty();
		if (!hasConfigurers) {
			WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
					.postProcess(new WebSecurityConfigurerAdapter() {
					});
			webSecurity.apply(adapter);
		}
             // 核心方法,返回FilterChainProxy
		return webSecurity.build();
	}

webSecurity.build()会触发AbstractConfiguredSecurityBuilder中的doBuild()方法,里面关键方法有init(),configurer()和performBuild(),最终返回FilterChainProxy

现在webSecurity里的属性configurers有3个:

securityConfig  (用户自定义类继承WebSecurityConfigurerAdapter)

ignoredPathsWebSecurityConfigurerApdater

SpringBootWebSecurityConfiguration

    @Override
	protected final O doBuild() throws Exception {
		synchronized (configurers) {
			buildState = BuildState.INITIALIZING;

			beforeInit();
             // 遍历init(),其中WebSecurityConfigurerAdapter的init()方法获取包含configurers的HttpSecurity实例,存入webSecurity中
			init();

			buildState = BuildState.CONFIGURING;

			beforeConfigure();
            // 遍历configure()
			configure();

			buildState = BuildState.BUILDING;
            //  执行WebSecurity的performBuild()方法,将SecurityFilterChainBuilders(即httpSecurity集合)遍历执行build()方法
            //  此时http.build()会将http里的configurers属性转换后写入filters中
            //  获得SecurityFilterChains,存入FilterChainProxy中并返回
			O result = performBuild();

			buildState = BuildState.BUILT;

			return result;
		}
	}

总结

如果你看了一遍发现什么也没记住,那么恭喜你,你已经达到了道家中无我的境界了

张三丰教张无忌太极拳,问他记住了多少。无忌说只记住了一半,再问记住多少,无忌想了会说已经全忘了,张三丰满意的笑了,现在你可以去会玄冥二老了。

上面讲的很零散,但都是基本,现在我们按程序执行顺序串着讲一遍,看能记住多少。

1.WebSecurityConfiguration初始化WebSecurity,并传入configurers(类型为WebSecurityConfigurer.class)属性,如WebSecurityConfigurerApdater继承类,IgnoredPathsWebSecurityConfigurerAdapter,ApplicationWebSecurityConfigurerAdapter等。最后执行webSecurity.build()返回FilterChainProxy,取名为"springSecurityFilterChain"。

2.webSecurity.build()方法会调用AbstractConfiguredSecurityBuilder.doBuild(),即遍历webSecurity.configurers,执行init()和configure(),最后performBuild()返回FilterChainProxy

2.1.WebSecurityConfigurerApdater.init()方法,通过getHttp()方法获得配置好的HttpSecurity,里面包含了configurers(如HeadersConfigurer,SecurityContextConfigure,LogoutConfigurer等)。将HttpSecurity添加到webSecurity的属性securityFilterChainBuilders集合里,以后在webSecurity.performBuild()中会调用。

2.2.WebSecurityConfigurerApdater.configure(webSecurity)方法,默认为空,继承类中可重写该方法

2.3.webSecurity.performBuild(),遍历securityFilterChainBuilders(即httpSecurity集合),执行http.build()方法获得DefaultSecurityFilterChain,存入新建的FilterChainProxy中并返回。其中http.build()方法会将http中的configures属性转换成filter添加到http.filters属性中,再根据http.performBuild()方法new DefaultSecurityFilterChain(requestMatcher,filters)并返回。

3.至此webSecurity.build()返还了FilterChainProxy,作为bean由spring管理,专门用于用户验证和资源授权。当用户访问uri时,FilterChainProxy执行doFilterInternal()方法,选择合适的SecurityFilterChain,提取其中的List<Filter> filters作为addtionalFilters依次执行。

3.1 UsernamePasswordAuthenticationFilter      providerManager.authenticate()    将authentication存入SecurityConext里和session中

3.2 FilterSecurityInterceptor  验证权限,成功则直接访问资源,失败则跳转到ExceptionTranslationFilter,接着跳转到登录界面

 

至此,FilterChainProxy从创建到调用整个流程我们就讲完了,记住多少就看个人造化了。下一章我们将着重介绍UsernamePasswordAuthenticationFilter是怎么运作的。

 

  • 11
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
org.springframework.security.authentication.InternalAuthenticationServiceException: null at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:123) ~[spring-security-core-5.3.4.RELEASE.jar:5.3.4.RELEASE] at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:144) ~[spring-security-core-5.3.4.RELEASE.jar:5.3.4.RELEASE] at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) ~[spring-security-core-5.3.4.RELEASE.jar:5.3.4.RELEASE] at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:95) ~[spring-security-web-5.3.4.RELEASE.jar:5.3.4.RELEASE] at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.3.4.RELEASE.jar:5.3.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.3.4.RELEASE.jar:5.3.4.RELEASE] at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.3.4.RELEASE.jar:5.3.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.3.4.RELEASE.jar:5.3.4.RELEASE] at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) [spring-security-web-5.3.4.RELEASE.jar:5.3.4.RELEASE] at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) [spring-security-web-5.3.4.RELEASE.jar:5.3.4.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.9.RELEASE.jar:5.2.9.
07-20
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值