阿八博客
  • 100000+

    文章

  • 23

    评论

  • 20

    友链

  • 最近新加了很多技术文章,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

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

欢迎来到阿八个人博客网站。本 阿八个人博客 网站提供最新的站长新闻,各种互联网资讯。 喜欢本站的朋友可以收藏本站,或者加QQ:我们大家一起来交流技术! URL链接:https://www.abboke.com/jsh/2019/1010/116514.html

  在认证过程和访问授权前必须了解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请求进行配置
其有很多方法,列举一些常用的如下表:

当使用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@EnableWebSecuritypublic 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顺序:

ChannelProcessingFilter访问协议控制过滤器,可能会将我们重新定向到另外一种协议,从http转换成httpsSecurityContextPersistenceFilter创建SecurityContext安全上下文信息和request结束时清空SecurityContextHolderConcurrentSessionFilter并发访问控制过滤器,主要功能:SessionRegistry中获取SessionInformation来判断session是否过期,从而实现并发访问控制
HeaderWriterFilter给http response添加一些HeaderCsrfFilter跨域过滤器,跨站请求伪造保护FilterLogoutFilter处理退出登录的FilterX509AuthenticationFilter添加X509预授权处理机制支持CasAuthenticationFilter认证filter,经过这些过滤器后SecurityContextHolder中将包含一个完全组装好的Authentication对象,从而使后续鉴权能正常执行UsernamePasswordAuthenticationFilter认证的filter,经过这些过滤器后SecurityContextHolder中将包含一个完全组装好的Authentication对象,从而使后续鉴权能正常执行
表单认证是最常用的一个认证方式
BasicAuthenticationFilter认证filter,经过这些过滤器后SecurityContextHolder中将包含一个完全组装好的Authentication对象,从而使后续鉴权能正常执行SecurityContextHolderAwareRequestFilter此过滤器对ServletRequest进行了一次包装,使得request具有更加丰富的APIJaasApiIntegrationFilter(JAAS)认证方式filterRememberMeAuthenticationFilter记忆认证处理过滤器,即是如果前面认证过滤器没有对当前的请求进行处理,启用了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笔记】 一起学习,每天会分享干货,还有学习视频领取!

相关文章

暂住......别动,不想说点什么吗?
  • 全部评论(0
    还没有评论,快来抢沙发吧!