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

“致"高级"工程师(BUG工程师)

一颗折腾的心??

原创不易,点个赞??,支持支持

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

1. WebSecurityConfigurerAdapter

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

  1. AuthenticationManagerBuilder:用来配置全局的认证相关的信息,其实就是AuthenticationProvider和UserDetailsService,前者是认证服务提供商,后者是用户详情查询服务;
  2. WebSecurity: 全局请求忽略规则配置(比如说静态文件,比如说注册页面)、全局HttpFirewall配置、是否debug配置、全局SecurityFilterChain配置、privilegeEvaluator、expressionHandler、securityInterceptor;
  3. 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() 添加自定义的filter addFilter(new CustomFilter())
addFilterAt() 在指定filter相同位置上添加自定义filter addFilterAt(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
addFilterAfter() 在指定filter位置后添加自定义filter addFilterAfter(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的工作原理以及在项目中出现的问题定位。了解完准备工作,接下来将展开对认证和访问授权模块的工作流程研究以及项目示例分析。最后如有错误可评论告知。

各位看官还可以吗?喜欢的话,动动手指点个赞??,点个关注呗!!谢谢支持!

也欢迎关注公众号【Ccww笔记】,原创技术文章第一时间推出

原文地址:https://www.cnblogs.com/Ccwwlx/p/11978429.html

时间: 2024-11-05 22:57:42

Spring Security(二)--WebSecurityConfigurer配置以及filter顺序的相关文章

CAS 与 Spring Security 3整合配置详解

一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分.用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统.用户授权指的是验证某个用户是否有权限执行某个操作.在一个系统中,不同用户所具有的权限是不同的.比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改.一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限. 对于上面提到的两种应用情景,Spring Security 框

CAS Spring Security 3 整合配置(转)

一般来说, Web 应用的安全性包括用户认证( Authentication )和用户授权( Authorization )两个部分.用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统.用户授权指的是验证某个用户是否有权限执行某个操作.在一 个系统中,不同用户所具有的权限是不同的.比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改.一般来说,系统会为不同的用户分配不同的 角色,而每个角色则对应一系列的权限. 对于上面提到的两种应用情景, Spring Se

Spring boot --- Spring Security(二)

   文章部分图片来自参考资料,这篇文章主要讲 spring security  oauth 概述 上一篇我们学习了 SS 中重要的工作原理和几个大概的认证和授权过程.而 spring security oauth 用到的就是 spring security 知识,我们学习 sso 之前先看一下oauth 是什么,可以学习阮一峰老师的文章 oauth 的流程图如下 : (牢牢记住这张图) 主要的角色有资源持有者,资源服务器,认证服务器,还有用户 授权(获取 Access Token)的方式有多种

【JavaEE】SSH+Spring Security基础上配置AOP+log4j

Spring Oauth2大多数情况下还是用不到的,主要使用的还是Spring+SpringMVC+Hibernate,有时候加上SpringSecurity,因此,本文及以后的文章的example中都不会包含oauth2的配置,需要的话把前文的applicationContext-security.xml和pom.xml加上就可以了,本文在“SSH+Spring Security搭建方法及example”一文的基础上做一些调整,主要内容是:配置Spring AOP并且用log4j来记录日志.

spring security自定义指南

序 本文主要研究一下几种自定义spring security的方式 主要方式 自定义UserDetailsService 自定义passwordEncoder 自定义filter 自定义AuthenticationProvider 自定义AccessDecisionManager 自定义securityMetadataSource 自定义access访问控制 自定义authenticationEntryPoint 自定义多个WebSecurityConfigurerAdapter 自定义User

Spring Security(09)——Filter

目录 1.1     Filter顺序 1.2     添加Filter到FilterChain 1.3     DelegatingFilterProxy 1.4     FilterChainProxy 1.5     Spring Security定义好的核心Filter 1.5.1    FilterSecurityInterceptor 1.5.2    ExceptionTranslationFilter 1.5.3    SecurityContextPersistenceFilt

Spring Security OAuth2 开发指南。

官方原文:http://projects.spring.io/spring-security-oauth/docs/oauth2.html 翻译及修改补充:Alex Liao. Spring OAuth2.0 提供者实现原理: Spring OAuth2.0提供者实际上分为: 授权服务 Authorization Service. 资源服务 Resource Service. 虽然这两个提供者有时候可能存在同一个应用程序中,但在Spring Security OAuth中你可以把 他它们各自放在

Spring Security 入门(1-14)Spring Security 开发指南(转)

开发指南:http://www.cnblogs.com/xingxueliao/p/5911292.html Spring OAuth2.0 提供者实现原理: Spring OAuth2.0提供者实际上分为: 授权服务 Authorization Service. 资源服务 Resource Service. 虽然这两个提供者有时候可能存在同一个应用程序中,但在Spring Security OAuth中你可以把 他它们各自放在不同的应用上,而且你可以有多个资源服务,它们共享同一个中央授权服 务

继续说说spring security之并发控制(Concurrency Control)

定义,作用,说明: Concurrency Control:并发控制,主要用于避免同一用户多次登录,重复登录以及包括相关的session管理--具体官网---> 先看官网:http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#session-mgmt 官网的并发控制已经说得比较清楚,但是偏偏有人(例如我)重写了(自定义了)验证的方法,导致了失效的问题,至此,一起说说s