当前位置: 首页 > news >正文

spring-security原理与应用系列:HttpSecurity.filters

目录

AnyRequestMatcher

WebSecurityConfig

HttpSecurity

AbstractInterceptUrlConfigurer

AbstractAuthenticationProcessingFilter

类图


        在前面的文章《spring-security原理与应用系列:securityFilterChainBuilders》中,我们遗留了一个问题:HttpSecurity建造者的build()方法最终构建的是DefaultSecurityFilterChain对象,该对象的两个构造参数requestMatcher和filters是如何初始化的呢?

        这篇文章,我们来了解其中跟filters对象相关的流程。       

        设置断点,如下所示:

        在这里, 我们看到requestMatcher对象的类型是AnyRequestMatcher,如下所示:

AnyRequestMatcher

public final class AnyRequestMatcher implements RequestMatcher {
   public static final RequestMatcher INSTANCE = new AnyRequestMatcher();
   public boolean matches(HttpServletRequest request) {
      return true;
   }

        在这里,matches()方法直接返回true,所以自定义配置的请求地址串也就没有放在这里了。

        所以,这个filters列表里所有的过滤器都会执行,这个与核心过滤器的filters对象有较大的区别。

        请求地址的匹配操作会在filters里的每个过滤器都进行一次过滤(除非中间执行过程中有不满足过滤器要求而提前结束HTTP请求)。

        所以,我们重点关注filters的对象即可。

        我们的自定义配置类如下所示:

WebSecurityConfig

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
   @Autowired
   private SecurityConfig securityConfig;
   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests()
            // 配置白名单(比如登录接口)
            .antMatchers(securityConfig.getPermitUrls()).permitAll()
            // 匿名访问的URL,即不用登录也可以访问(比如广告接口)
            .antMatchers(securityConfig.getAnonymousUrls()).permitAll()
            // 买家接口需要 “ROLE_BUYER” 角色权限才能访问
            .antMatchers("/buyer/**").hasRole("BUYER")
            // 其他任何请求满足 rbacService.hasPermission() 方法返回true时,能够访问
            .anyRequest().access("@rbacService.hasPermission(request, authentication)")
          ... ...

   }

        点击authorizeRequests(),如下所示:

HttpSecurity

public ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequests() throws Exception {
   ApplicationContext context = getContext();
   return getOrApply(new ExpressionUrlAuthorizationConfigurer<HttpSecurity>(context))
         .getRegistry();
}

         在这里,将配置器ExpressionUrlAuthorizationConfigurer使用于建造者HttpSecurity中。

        通过前面的章节,我们知道,建造者在建造对象时,会调用配置器的configure()方法,找到配置器ExpressionUrlAuthorizationConfigurer的configure()方法,如下所示:

AbstractInterceptUrlConfigurer

abstract class AbstractInterceptUrlConfigurer<C extends AbstractInterceptUrlConfigurer<C, H>, H extends HttpSecurityBuilder<H>>
      extends AbstractHttpConfigurer<C, H> {
   private Boolean filterSecurityInterceptorOncePerRequest;
   private AccessDecisionManager accessDecisionManager;
   @Override
   public void configure(H http) throws Exception {
      FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http);
      if (metadataSource == null) {
         return;
      }
      FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(
            http, metadataSource, http.getSharedObject(AuthenticationManager.class));
      if (filterSecurityInterceptorOncePerRequest != null) {
         securityInterceptor
               .setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest);
      }
      securityInterceptor = postProcess(securityInterceptor);
      http.addFilter(securityInterceptor);
      http.setSharedObject(FilterSecurityInterceptor.class, securityInterceptor);
   }

        在这里,果不其然,我们看到了往建造者HttpSecurity对象添加过滤器filter的代码http.addFilter(securityInterceptor)。该过滤器的类型是FilterSecurityInterceptor。

        通过上面的分析,我们知道,请求地址的匹配操作会在filters里的每个过滤器都进行一次过滤(除非中间执行过程中有不满足过滤器要求而提前结束HTTP请求的)。

        接下来,我们找一个比较简单的过滤器,了解一下这些过滤器是如何进行请求地址匹配的,如下所示:

AbstractAuthenticationProcessingFilter

public abstract class AbstractAuthenticationProcessingFilter extends GenericFilterBean
      implements ApplicationEventPublisherAware, MessageSourceAware {

... ...

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws IOException, ServletException {
   HttpServletRequest request = (HttpServletRequest) req;
   HttpServletResponse response = (HttpServletResponse) res;
   if (!requiresAuthentication(request, response)) {
      chain.doFilter(request, response);
      return;
   }
   Authentication authResult;
   try {
      authResult = attemptAuthentication(request, response);
      if (authResult == null) {
         return;
      }
      sessionStrategy.onAuthentication(authResult, request, response);
   }
   catch (InternalAuthenticationServiceException failed) {
      unsuccessfulAuthentication(request, response, failed);
      return;
   }
   catch (AuthenticationException failed) {
      unsuccessfulAuthentication(request, response, failed);
      return;
   }
   if (continueChainBeforeSuccessfulAuthentication) {
      chain.doFilter(request, response);
   }
   successfulAuthentication(request, response, chain, authResult);
}

        在这里,通过调用!requiresAuthentication(request, response)判断是否需要对当前请求进行认证,不需要则执行下一个过滤器,需要则进行认证操作。

        点击requiresAuthentication()方法,如下所示:

protected boolean requiresAuthentication(HttpServletRequest request,
      HttpServletResponse response) {
   return requiresAuthenticationRequestMatcher.matches(request);
}

       spring-security还内置了许多的过滤器,如下所示:

       这些过滤器给我们的开发工作带来了你很大的方便,减少了大量的工作,这个后续我们再探究。

        如下是与过滤器FilterSecurityInterceptor相关的类图:

类图

        这里是与过滤器FilterSecurityInterceptor的Configurer相关的类图。

        这里是配置器的属性ExpressionInterceptUrlRegistry相关的类图。

       这里是过滤器FilterSecurityInterceptor相关的类图。这个过滤器比较复杂与比较重要,我们后续再专门开一篇文章进行探究。

http://www.dtcms.com/a/108056.html

相关文章:

  • 【算法中的数学】欧拉筛埃氏筛
  • 游戏引擎学习第194天
  • SpringBoot+Vue 中 WebSocket 的使用
  • LLM大模型教程——什么是AI大模型
  • 企业linux常用服务搭建
  • 数据结构每日一题day10(链表)★★★★★
  • Ansible(3)——主机清单与配置文件
  • 【高项】信息系统项目管理师(十四)配置与变更管理【3分】
  • unity点击button后不松开通过拖拽显示模型松开后模型实例化
  • 【工业场景】用YOLOv12实现饮料类别识别
  • 基于神经网络的肾脏疾病预测模型
  • 单元测试原则之——不要模拟不属于你的类型
  • 亚马逊云科技赋能英矽智能,打破新药研发“双十”定律
  • VASP计算过渡态(CI-NEB)初始结构生成脚本汇总
  • 【MySQL篇】limit深度分页性能:从原理理解小偏移量limit 1,200 vs 百万级偏移量limit 1000000,200的差异
  • DirectX安装及使用教程(附安装包)
  • MongoDB安装完整教程
  • Transformer【学习记录】
  • react使用eventBus在不同模块间进行通信
  • Synology NAS 部署WPS-Office
  • zk基础—3.集群与核心参数二
  • 2025年优化算法:真菌生长优化算法(Fungal Growth Optimizer,FGO)
  • 【NetCore】ControllerBase:ASP.NET Core 中的基石类
  • 长短期记忆神经网络(LSTM)基础学习与实例:预测序列的未来
  • 外卖平台问题
  • 未来幻想世界
  • JAVA学习小计之IO流01-字节流篇
  • Axure 使用笔记
  • leetcode:3083. 字符串及其反转中是否存在同一子字符串(python3解法)
  • 算法设计与分析之“分治法”