Spring Security(二)--WebSecurityConfigurer配置以及filter顺序

在认证过程和访问授权前必须了解spring Security如何知道我们要求所有用户都经过身份验证? Spring Security如何知道我们想要支持基于表单的身份验证?因此必须了解WebSecurityConfigurerAdapter配置类如何工作的。而且也必须了解清楚filter的顺序,才能更好了解其调用工作流程。

  1. WebSecurityConfigurerAdapter
      在使用WebSecurityConfigurerAdapter前,先了解Spring security config。
      Spring security config具有三个模块,一共有3个builder,认证相关的AuthenticationManagerBuilder和web相关的WebSecurity、HttpSecurity。

AuthenticationManagerBuilder:用来配置全局的认证相关的信息,其实就是AuthenticationProvider和UserDetailsService,前者是认证服务提供商,后者是用户详情查询服务;

WebSecurity: 全局请求忽略规则配置(比如说静态文件,比如说注册页面)、全局HttpFirewall配置、是否debug配置、全局SecurityFilterChain配置、privilegeEvaluator、expressionHandler、securityInterceptor;

HttpSecurity:具体的权限控制规则配置。一个这个配置相当于xml配置中的一个标签。各种具体的认证机制的相关配置,OpenIDLoginConfigurer、AnonymousConfigurer、FormLoginConfigurer、HttpBasicConfigurer等。
  WebSecurityConfigurerAdapter提供了简洁方式来创建WebSecurityConfigurer,其作为基类,可通过实现该类自定义配置类,主要重写这三个方法:

 protected void configure(AuthenticationManagerBuilder auth) throws Exception {}
 public void configure(WebSecurity web) throws Exception {}
 protected void configure(HttpSecurity httpSecurity) throws Exception {}

而且其自动从SpringFactoriesLoader查找AbstractHttpConfigurer让我们去扩展,想要实现必须创建一个AbstractHttpConfigurer的扩展类,并在classpath路径下创建一个文件META-INF/spring.factories。例如:
org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyClassThatExtendsAbstractHttpConfigurer
其源码分析:
//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初始化模块中的“获取HttpSecurity”和“配置FilterSecurityInterceptor拦截器到WebSecurity”中可以看出,想要spring Security如何知道我们要求所有用户都经过身份验证? Spring Security如何知道我们想要支持基于表单的身份验证?只要重写protected void configure(HttpSecurity http) throws Exception方法即可。因此我们需要理解HttpSecurity的方法的作用,如何进行配置。下一节来讨论HttpSecurity。
2. HttpSecurity

HttpSecurity基于Web的安全性允许为特定的http请求进行配置。其有很多方法,列举一些常用的如下表:

方法说明使用案例
csrf()添加 CSRF 支持,使用WebSecurityConfigurerAdapter时,默认启用禁用:csrf().disable()
openidLogin()用于基于 OpenId 的验证openidLogin().permitAll();
authorizeRequests()开启使用HttpServletRequest请求的访问限制authorizeRequests().anyRequest().authenticated()
formLogin()开启表单的身份验证,如果未指定FormLoginConfigurer#loginPage(String),则将生成默认登录页面formLogin().loginPage("/authentication/login").failureUrl("/authentication/login?failed")
oauth2Login()开启OAuth 2.0或OpenID Connect 1.0身份验证authorizeRequests()..anyRequest().authenticated()..and().oauth2Login()
rememberMe()开启配置“记住我”的验证authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin().permitAll().and().rememberMe()
addFilter()添加自定义的filteraddFilter(new CustomFilter())
addFilterAt()在指定filter相同位置上添加自定义filteraddFilterAt(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
addFilterAfter()在指定filter位置后添加自定义filteraddFilterAfter(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
requestMatchers()开启配置HttpSecurity,仅当RequestMatcher相匹配时开启requestMatchers().antMatchers("/api/**")
antMatchers()其可以与authorizeRequests()、RequestMatcher匹配,如:requestMatchers().antMatchers("/api/**")
logout()添加退出登录支持。当使用WebSecurityConfigurerAdapter时,这将自动应用。默认情况是,访问URL”/ logout”,使HTTP Session无效来清除用户,清除已配置的任何#rememberMe()身份验证,清除SecurityContextHolder,然后重定向到”/login?success”logout().deleteCookies("remove").invalidateHttpSession(false).logoutUrl("/custom-logout").logoutSuccessUrl("/logout-success");

HttpSecurity还有很多方法供我们使用,去配置HttpSecurity。由于太多这边就不一一说明,有兴趣可去研究。
3. WebSecurityConfigurerAdapter使用
WebSecurityConfigurerAdapter示例:
@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:此示例只供参考
4. filter顺序
Spring Security filter顺序:

Filter Class说明
ChannelProcessingFilter访问协议控制过滤器,可能会将我们重新定向到另外一种协议,从http转换成https
SecurityContextPersistenceFilter创建SecurityContext安全上下文信息和request结束时清空SecurityContextHolder
ConcurrentSessionFilter并发访问控制过滤器,主要功能:SessionRegistry中获取SessionInformation来判断session是否过期,从而实现并发访问控制。
HeaderWriterFilter给http response添加一些Header
CsrfFilter跨域过滤器,跨站请求伪造保护Filter
LogoutFilter处理退出登录的Filter
X509AuthenticationFilter添加X509预授权处理机制支持
CasAuthenticationFilter认证filter,经过这些过滤器后SecurityContextHolder中将包含一个完全组装好的Authentication对象,从而使后续鉴权能正常执行
UsernamePasswordAuthenticationFilter认证的filter,经过这些过滤器后SecurityContextHolder中将包含一个完全组装好的Authentication对象,从而使后续鉴权能正常执行。表单认证是最常用的一个认证方式。
BasicAuthenticationFilter认证filter,经过这些过滤器后SecurityContextHolder中将包含一个完全组装好的Authentication对象,从而使后续鉴权能正常执行
SecurityContextHolderAwareRequestFilter此过滤器对ServletRequest进行了一次包装,使得request具有更加丰富的API
JaasApiIntegrationFilter(JAAS)认证方式filter
RememberMeAuthenticationFilter记忆认证处理过滤器,即是如果前面认证过滤器没有对当前的请求进行处理,启用了RememberMe功能,会从cookie中解析出用户,并进行认证处理,之后在SecurityContextHolder中存入一个Authentication对象。
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的工作原理以及在项目中出现的问题定位。了解完准备工作,接下来将展开对认证和访问授权模块的工作流程研究以及项目示例分析。最后如有错误可评论告知。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring SecuritySpring 框架中的一个模块,用于实现应用程序的安全性和身份验证。Spring Security 提供了许多功能,如身份验证、授权、会话管理、密码编码、方法级别的安全性等。在 Spring Boot 应用程序中,可以使用 Spring Security 的自动配置来快速配置安全性。 Spring Boot 自动配置 Spring Security 的过程如下: 1. Spring Boot 自动装配了一个名为 springSecurityFilterChain 的 Filter。 2. Spring SecurityWebSecurityConfigurerAdapter 自动配置类被激活。 3. 如果没有定义任何 WebSecurityConfigurer,则应用程序将采用默认的 WebSecurityConfigurer。 4. 如果存在多个 WebSecurityConfigurer,则可以通过 @Order 注解来指定它们的顺序。 5. 如果需要自定义 WebSecurityConfigurerAdapter,则需要扩展该类,并覆盖 configure() 方法。 Spring Security 的自动配置可以通过在应用程序中添加以下依赖关系来启用: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> ``` 这个依赖关系会自动配置 Spring Security,包括使用默认的身份验证和授权设置、默认的登录页面和默认的用户。如果需要自定义这些设置,则需要在应用程序中添加相应的配置类或方法。 ### 回答2: Spring Security是一个基于Spring框架的安全框架,它提供了一系列的工具和功能来保护应用程序的安全性。Spring Security的自动装配是指通过Spring框架自动配置了一些常见的安全功能,简化了开发者的配置工作。 Spring Security的自动装配主要包括以下几个方面: 1. 用户认证:Spring Security自动装配了一个AuthenticationManager Bean,该Bean负责处理用户登录的认证过程。开发者只需要提供一个实现了UserDetailsService接口的Bean,并进行相应的配置,即可实现基于数据库或其他认证方式的用户认证。 2. 授权管理:Spring Security的自动装配中包含了一系列用于授权管理的类和接口,例如AccessDecisionManager、AccessDecisionVoter等。通过这些组件,开发者可以方便地配置应用程序的访问控制规则,并实现细粒度的权限控制。 3. 安全过滤器链:Spring Security的自动装配还会自动创建一个安全过滤器链,用于处理用户请求的安全验证和授权。这个过滤器链包括了一系列的过滤器,例如UsernamePasswordAuthenticationFilter、BasicAuthenticationFilter等。开发者可以根据自己的需求,对这些过滤器进行配置和扩展。 4. 表单登录和注销:Spring Security自动装配了一个与表单登录相关的默认配置,包括了一个登录页面、处理登录请求的Controller和相关的过滤器等。开发者可以通过自定义的方式,进行表单登录页面和注销功能的定制。 总之,Spring Security的自动装配大大简化了安全功能的配置和使用,使开发者能够更加方便地实现应用程序的安全保护,减少了开发工作量,提高了开发效率。 ### 回答3: Spring Security的自动装配是Spring Security框架提供的一种方便的配置方式,它可以大大简化我们在Spring应用程序中使用Spring Security配置工作。 首先,自动装配通过在Spring Security的依赖项中包含相应的库和组件,使得其能够与Spring框架集成和协同工作。当我们在项目中引入Spring Security依赖时,它会自动对一些常见的安全配置进行默认的自动配置。 其次,自动装配还提供了一些默认的安全配置选项,如基于内存的用户认证、基于表达式的方法级别的安全控制等。这些默认配置可以满足大多数应用程序的基本安全需求,无需进行复杂的手动配置。 第三,自动装配允许我们通过扩展现有的配置类或使用注解来自定义和修改默认的安全配置。我们可以通过创建自定义的配置类并继承自Spring Security提供的配置类,来覆盖默认的安全配置。我们也可以使用注解来指定需要保护的URL路径、配置用户的认证信息以及定义访问规则等。 最后,自动装配还支持集成其他认证和授权提供者,如LDAP、OAuth2等,并提供了一些简单易用的API和工具类,用于处理常见的身份验证和授权场景。 总的来说,Spring Security的自动装配是一种简化我们在Spring应用程序中使用Spring Security配置工作的方式。它提供了默认的安全配置选项,并允许我们进行自定义和修改,以满足不同应用程序的安全需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值