Spring Security (two) - WebSecurityConfigurer configuration and filter order

  Before the authentication process and access authorization must know how to spring Security know that we require all users to have authenticated? We want to know how Spring Security supports forms-based authentication? Therefore, you must understand how to configure WebSecurityConfigurerAdapter type of work. But also must understand clearly the order of the filter, in order to better understand their calling workflow.

1. WebSecurityConfigurerAdapter

  Providing WebSecurityConfigurerAdapter simple way to create WebSecurityConfigurer, as the base class, the class may be achieved by custom configuration class. It automatically finds AbstractHttpConfigurer extend from SpringFactoriesLoader Let's go, you want to achieve you must create a class extending AbstractHttpConfigurer and creates a file META-INF / spring.factories path in the classpath. E.g:

 org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyClassThatExtendsAbstractHttpConfigurer
复制代码

Its source code analysis:

   //1.init初始化:获取HttpSecurity和配置FilterSecurityInterceptor拦截器到WebSecurity
    public void init(final WebSecurity web) throws Exception {
            //获取HttpSecurity
	   final HttpSecurity http = getHttp();
    	//配置FilterSecurityInterceptor拦截器到WebSecurity
	    web.addSecurityFilterChainBuilder(http).postBuildAction(new Runnable() {
	    	public void run() {
		    	FilterSecurityInterceptor securityInterceptor = http
				    	.getSharedObject(FilterSecurityInterceptor.class);
		    	web.securityInterceptor(securityInterceptor);
		    }
	    });
    }
    ......
    //2.获取HttpSecurity的过程
    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) {
		// 默认的HttpSecurity的配置
		http
	                //添加 CSRF 支持,使用WebSecurityConfigurerAdapter时,默认启用,禁用csrf().disable()
			.csrf().and() 
			//添加WebAsyncManagerIntegrationFilter
			.addFilter(new WebAsyncManagerIntegrationFilter())
			//允许配置异常处理
			.exceptionHandling().and()
			//将安全标头添加到响应
			.headers().and()
			//允许配置会话管理
			.sessionManagement().and()
			//HttpServletRequest之间的SecurityContextHolder创建securityContext管理
			.securityContext().and()
			//允许配置请求缓存
			.requestCache().and()
			//允许配置匿名用户
			.anonymous().and()
			//HttpServletRequestd的方法和属性注册在SecurityContext中
			.servletApi().and()
			//使用默认登录页面
			.apply(new DefaultLoginPageConfigurer<>()).and()
			//提供注销支持
			.logout();
		// @formatter:on
		ClassLoader classLoader = this.context.getClassLoader();
		List<AbstractHttpConfigurer> defaultHttpConfigurers =
				SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);

		for(AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
			http.apply(configurer);
		}
	}
	configure(http);
	return http;
    }
...
//3.可重写方法实现自定义的HttpSecurity
protected void configure(HttpSecurity http) throws Exception {
	logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");

	http
		.authorizeRequests()
			.anyRequest().authenticated()
			.and()
		.formLogin().and()
		.httpBasic();
}
....
复制代码

  Init initialization module source code can be seen in the "Get HttpSecurity" and "Configuring FilterSecurityInterceptor interceptors to WebSecurity" from the Security wants to know how the spring we require that all users be authenticated? We want to know how Spring Security supports forms-based authentication? As long throws Exception methods can be rewritten protected void configure (HttpSecurity http). So we need to understand the role of HttpSecurity method, and how to configure it. The next section to discuss HttpSecurity.

2. HttpSecurity

  HttpSecurity Web-based security allows configurations for specific http request. There are many ways which, some commonly used include the following table:

method Explanation Use Cases
csrf() Add CSRF support, use WebSecurityConfigurerAdapter, enabled by default Disable:. Csrf () disable ()
openidLogin() Based on the verification OpenId openidLogin().permitAll();
authorizeRequests() Limit the use of open access HttpServletRequest request authorizeRequests().anyRequest().authenticated()
form login () Open forms of authentication, if FormLoginConfigurer # loginPage unspecified (String), it will generate a default login page formLogin().loginPage("/authentication/login").failureUrl("/authentication/login?failed")
oauth2Login() Open OAuth 2.0 authentication or OpenID Connect 1.0 authorizeRequests()..anyRequest().authenticated()..and().oauth2Login()
rememberMe() Open configuration "Remember Me" test authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin().permitAll().and().rememberMe()
addFilter() Adding custom filter addFilter(new CustomFilter())
addFilterAt () Add custom filter at the same position on the filter specified addFilterAt(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
addFilterAfter () Add custom filter specified in the filter position addFilterAfter(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
requestMatchers() Open configuration HttpSecurity, open only when the match RequestMatcher requestMatchers().antMatchers("/api/**")
antMatchers() RequestMatcher matching for use with requestMatchers () requestMatchers().antMatchers("/api/**")
logout() Add Log support. When WebSecurityConfigurerAdapter, which will be applied automatically. By default, the access URL "/ logout", the HTTP Session invalid user to clear, clear any #rememberMe () authentication configured, clear SecurityContextHolder, and then redirected to the "/ login? Success" logout().deleteCookies("remove").invalidateHttpSession(false).logoutUrl("/custom-logout").logoutSuccessUrl("/logout-success");

HttpSecurity There are many ways for us to use to configure HttpSecurity. So many here not setting them, are interested can go to study.

3. WebSecurityConfigurerAdapter使用

WebSecurityConfigurerAdapter example:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 @Autowired
 private MyFilterSecurityInterceptor myFilterSecurityInterceptor;
 protected void configure(HttpSecurity http) throws Exception {    
     http
     //request 设置
     .authorizeRequests()   //http.authorizeRequests() 方法中的自定义匹配
     .antMatchers("/resources/**", "/signup", "/about").permitAll() // 指定所有用户进行访问指定的url          
     .antMatchers("/admin/**").hasRole("ADMIN")  //指定具有特定权限的用户才能访问特定目录,hasRole()方法指定用户权限,且不需前缀 “ROLE_“  
     .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")//          
     .anyRequest().authenticated()  //任何请求没匹配的都需要进行验证                                           
     .and()        //login设置  自定义登录页面且允许所有用户登录
     .formLogin()      
     .loginPage("/login") //The updated configuration specifies the location of the log in page  指定自定义登录页面
     .permitAll(); // 允许所有用户访问登录页面. The formLogin().permitAll() 方法
     .and 
     .logout()  //logouts 设置                                                              
     .logoutUrl("/my/logout")  // 指定注销路径                                              
     .logoutSuccessUrl("/my/index") //指定成功注销后跳转到指定的页面                                        
     .logoutSuccessHandler(logoutSuccessHandler)  //指定成功注销后处理类 如果使用了logoutSuccessHandler()的话, logoutSuccessUrl()就会失效                                
     .invalidateHttpSession(true)  // httpSession是否有效时间,如果使用了 SecurityContextLogoutHandler,其将被覆盖                                        
     .addLogoutHandler(logoutHandler)  //在最后增加默认的注销处理类LogoutHandler                
     .deleteCookies(cookieNamesToClear);//指定注销成功后remove cookies
     //增加在FilterSecurityInterceptor前添加自定义的myFilterSecurityInterceptor
     http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);
   }
复制代码

NOTE: This example is for reference only

4. filter order

Spring Security filter order:

Filter Class Explanation
ChannelProcessingFilter Access control protocol filters, we might redirect to another protocol, switching from http to https
SecurityContextPersistenceFilter Create a security context SecurityContext SecurityContextHolder emptied at the end of the information and request
ConcurrentSessionFilter Concurrent access control filters, the main functions: SessionRegistry acquired SessionInformation determines whether the session expires, which concurrent access control.
HeaderWriterFilter Http response to add some Header
CsrfFilter Cross-domain filters, Filter CSRF protection
LogoutFilter Log handling of Filter
X509AuthenticationFilter Add pre-authorization processing mechanism X509 support
CasAuthenticationFilter Authentication filter, after which the filter will comprise a fully assembled SecurityContextHolder Authentication object, so that the subsequent authentication can be performed normally
UsernamePasswordAuthenticationFilter Certified filter, after which the filter will comprise a fully assembled SecurityContextHolder Authentication object, so that the subsequent authentication can be performed properly. Forms authentication is the most common way a certification.
BasicAuthenticationFilter Authentication filter, after which the filter will comprise a fully assembled SecurityContextHolder Authentication object, so that the subsequent authentication can be performed normally
SecurityContextHolderAwareRequestFilter This filter of ServletRequest had a package such request has a richer API
JaasApiIntegrationFilter (JAAS) authentication filter
RememberMeAuthenticationFilter Authentication processing filter memory, i.e., if the front filter is not performed authentication processing of the current request is enabled RememberMe function parses the cookie from the user, and the authentication process, after an Authentication object stored in the SecurityContextHolder.
AnonymousAuthenticationFilter 匿名认证处理过滤器,当SecurityContextHolder中认证信息为空,则会创建一个匿名用户存入到SecurityContextHolder中
SessionManagementFilter 会话管理Filter,持久化用户登录信息,可以保存到session中,也可以保存到cookie或者redis中
ExceptionTranslationFilter 异常处理过滤器,主要拦截后续过滤器(FilterSecurityInterceptor)操作中抛出的异常。
FilterSecurityInterceptor 安全拦截过滤器类,获取当前请求url对应的ConfigAttribute,并调用accessDecisionManager进行访问授权决策。

spring security的默认filter链:

 SecurityContextPersistenceFilter
->HeaderWriterFilter
->LogoutFilter
->UsernamePasswordAuthenticationFilter
->RequestCacheAwareFilter
->SecurityContextHolderAwareRequestFilter
->SessionManagementFilter
->ExceptionTranslationFilter
->FilterSecurityInterceptor
复制代码

在上节我们已分析了核心的filter源码以及功能。可回看上节源码分析更加深入的了解各个filter工作原理。

总结:

  在认证和访问授权过程前,首先必须进行WebSecurityConfigurer符合自身应用的security Configurer,也要清楚filter链的先后顺序,才能更好理解spring security的工作原理以及在项目中出现的问题定位。了解完准备工作,接下来将展开对认证和访问授权模块的工作流程研究以及项目示例分析。最后如有错误可评论告知。

转载于:https://juejin.im/post/5d0b1eb35188252f921b1535

Guess you like

Origin blog.csdn.net/weixin_34104341/article/details/93181624