首页 > 编程语言 >[SpringSecurity5.6.2源码分析六]:ChannelProcessingFilter

[SpringSecurity5.6.2源码分析六]:ChannelProcessingFilter

时间:2023-09-11 15:07:01浏览次数:42  
标签:SpringSecurity5.6 http request return 安全 源码 new ChannelProcessingFilter attribut

1、基础用法

  • • ChannelProcessingFilter是SpringSecurity的第一个过滤器,具体排序规则见FilterComparator,

[SpringSecurity5.6.2源码分析六]:ChannelProcessingFilter_源码

image.png

  • • 主要作用:可限制服务端接受的安全协议,比如说仅支持Https或者Http

1.1 开启配置类:

  • • 首先我们注册到容器中的WebSecurityConfigurerAdapter是针对于WebSecurity的配置类,但是像Cors、Csrf等等功能是靠HttpSecurity配置的, 我们可以通过重写此方法,并通过requiresChannel()注册一个ChannelSecurityConfigurer,这是用于配置通道的配置类
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    ......
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requiresChannel();
   }
   ......
}

1.2 使用

  • • 注册通道处理器(ChannelProcessor)
http.requiresChannel().channelProcessors(list)
  • • 通道处理器是用于用于判断是否满足某些安全条件,比如说
  • • InsecureChannelProcessor:要求请求使用非安全通道
  • • SecureChannelProcessor:要求请求使用安全通道
  • • 针对于哪些请求需要进行安全通道的限制
http.requiresChannel().mvcMatchers("/*").requires("REQUIRES_SECURE_CHANNEL")
http.requiresChannel().mvcMatchers("/*").requires("REQUIRES_INSECURE_CHANNEL")
  • • 注册一个ObjectPostProcessor,让过滤器在创建完成后执行的回调方法
http.requiresChannel().withObjectPostProcessor(new ObjectPostProcessor<ChannelProcessingFilter>() {
   @Override
   public <O extends ChannelProcessingFilter> O postProcess(O object) {
      return object;
   }
});
  • • 这并不是当前介绍的这个过滤器独有,而应该是大部分过滤器都应该具备的,比如说ExceptionTranslationFilter,BasicAuthenticationFilter等等过滤器都具备的,都是在对应的配置类中负责执行的

2、ChannelSecurityConfigurer

  • • 所有的配置类都是基于建造者模式进行的
@Override
protected final O doBuild() throws Exception {
  synchronized (configurers) {
     buildState = BuildState.INITIALIZING;

     beforeInit();
     init();

     buildState = BuildState.CONFIGURING;

     beforeConfigure();
     configure();

     buildState = BuildState.BUILDING;

     O result = performBuild();

     buildState = BuildState.BUILT;

     return result;
  }
}
  • • ChannelSecurityConfigurer只重写了configure方法,这里也只讲这个,这里出现了两个新的类
  • • ChannelDecisionManagerImpl:负责管理注册的ChannelProcessor
  • • DefaultFilterInvocationSecurityMetadataSource:主要是根据请求确定本次请求需要具备哪些安全属性或者说权限
@Override
public void configure(H http) {
   ChannelDecisionManagerImpl channelDecisionManager = new ChannelDecisionManagerImpl();
   //设置通道处理器
   channelDecisionManager.setChannelProcessors(getChannelProcessors(http));
   channelDecisionManager = postProcess(channelDecisionManager);
   //设置通道决策管理器
   this.channelFilter.setChannelDecisionManager(channelDecisionManager);

   //设置安全元数据源
   DefaultFilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource = new DefaultFilterInvocationSecurityMetadataSource(
         this.requestMap);
   this.channelFilter.setSecurityMetadataSource(filterInvocationSecurityMetadataSource);
   this.channelFilter = postProcess(this.channelFilter);
   http.addFilter(this.channelFilter);
}
  • • 第6行和14行代码就是要执行注册的ObjectPostProcessor
  • • 接下来看getChannelProcessors(http)方法
/**
 * 获得通道处理器
 * @param http
 * @return
 */
private List<ChannelProcessor> getChannelProcessors(H http) {
   if (this.channelProcessors != null) {
      return this.channelProcessors;
   }

   //创建安全通过处理器
   InsecureChannelProcessor insecureChannelProcessor = new InsecureChannelProcessor();
   SecureChannelProcessor secureChannelProcessor = new SecureChannelProcessor();


   PortMapper portMapper = http.getSharedObject(PortMapper.class);
   if (portMapper != null) {

      RetryWithHttpEntryPoint httpEntryPoint = new RetryWithHttpEntryPoint();
      httpEntryPoint.setPortMapper(portMapper);
      insecureChannelProcessor.setEntryPoint(httpEntryPoint);
      //创建不安全通过处理器
      RetryWithHttpsEntryPoint httpsEntryPoint = new RetryWithHttpsEntryPoint();
      httpsEntryPoint.setPortMapper(portMapper);
      secureChannelProcessor.setEntryPoint(httpsEntryPoint);
   }
   insecureChannelProcessor = postProcess(insecureChannelProcessor);
   secureChannelProcessor = postProcess(secureChannelProcessor);
   return Arrays.asList(insecureChannelProcessor, secureChannelProcessor);
}
  • • 可以看到当我们没有为其注册通道处理器的时候,默认是注册两个,一个是要求安全的一个是非安全的
  • • 这里出现了两个新类:PortMapper和RetryWithHttpEntryPoint
  • • PortMapper:如果是系统要求使用安全的也就是Https那么就需要进行重定向,但是重定向后的端口怎么确定呢,就是靠这个类
  • • 可以看出默认就只有两个端口的转换
public PortMapperImpl() {
   this.httpsPortMappings = new HashMap<>();
   this.httpsPortMappings.put(80, 443);
   this.httpsPortMappings.put(8080, 8443);
}
  • • RetryWithHttpEntryPoint:当请求的安全协议不支持的时候,进行重定向操作
@Override
public void commence(HttpServletRequest request, HttpServletResponse response) throws IOException {
   String queryString = request.getQueryString();
   String redirectUrl = request.getRequestURI() + ((queryString != null) ? ("?" + queryString) : "");
   Integer currentPort = this.portResolver.getServerPort(request);
   Integer redirectPort = getMappedPort(currentPort);

   if (redirectPort != null) {
      // http和https默认的端口不需要设置
      boolean includePort = redirectPort != this.standardPort;
      String port = (includePort) ? (":" + redirectPort) : "";

      redirectUrl = this.scheme + request.getServerName() + port + redirectUrl;
   }
   this.logger.debug(LogMessage.format("Redirecting to: %s", redirectUrl));
   // 设置重定向Url
   this.redirectStrategy.sendRedirect(request, response, redirectUrl);
}

3、ChannelProcessingFilter

  • • 此过滤器就两个方法:afterPropertiesSet() 和 doFilter(......)
  • • afterPropertiesSet():检查注册的安全属性是否合法
@Override
public void afterPropertiesSet() {
   ......
   // 获取所有安全属性
   Collection<ConfigAttribute> attrDefs = this.securityMetadataSource
         .getAllConfigAttributes();

   if (attrDefs == null) {
      if (this.logger.isWarnEnabled()) {
         this.logger
               .warn("Could not validate configuration attributes as the FilterInvocationSecurityMetadataSource did "
                     + "not return any attributes");
      }

      return;
   }

   Set<ConfigAttribute> unsupportedAttributes = new HashSet<>();

   // 判断通道管理器中的通道处理器是否支持对于的安全属性(权限)
   for (ConfigAttribute attr : attrDefs) {
      if (!this.channelDecisionManager.supports(attr)) {
         unsupportedAttributes.add(attr);
      }
   }

   // 不为空就说明有安全属性不支持直接抛出异常
   if (unsupportedAttributes.size() == 0) {
      if (this.logger.isInfoEnabled()) {
         this.logger.info("Validated configuration attributes");
      }
   }
   else {
      throw new IllegalArgumentException(
            "Unsupported configuration attributes: " + unsupportedAttributes);
   }
}
  • • doFilter(......):
  • • 第一步:通过安全元数据源获得接口所需权限
  • • 第二步:调用通道决策管理器判断请求是否合法,如果不合法就会在内部设置重定向的参数,然后这里就会直接返回了
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws IOException, ServletException {

   //包装请求
   HttpServletRequest request = (HttpServletRequest) req;
   HttpServletResponse response = (HttpServletResponse) res;
   FilterInvocation filterInvocation = new FilterInvocation(request, response, chain);

   //通过安全元数据源获得接口所需权限
   Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(filterInvocation);
   if (attributes != null) {
      this.logger.debug(LogMessage.format("Request: %s; ConfigAttributes: %s", filterInvocation, attributes));
      //调用通道决策管理器
      this.channelDecisionManager.decide(filterInvocation, attributes);
      //是否已经完成
      if (filterInvocation.getResponse().isCommitted()) {
         return;
      }
   }
   chain.doFilter(request, response);
}


标签:SpringSecurity5.6,http,request,return,安全,源码,new,ChannelProcessingFilter,attribut
From: https://blog.51cto.com/u_14008019/7435928

相关文章

  • 一套UWB室内外高精度定位系统源码
    智慧工厂是现代工厂信息化发展的新阶段,基于UWB定位技术,融合位置物联网、GIS可视化等技术,实现对人员、物资精确管理。在重点区域设置电子围栏,无权限人员进入即刻告警;对人员超/缺员、串岗滞留等规范化管理,提升工厂的秩序管理及生产效率。定位能力:支持零维、一维、二维等多种定位方式,......
  • 直播系统源码平台内容安全与版权维护技术:DRM
    在数字化的时代,人们的生活中已深入到网络中来,许多人加入了直播系统源码平台中来,直播系统源码平台为用户们提供了一个发布图文短视频、开启直播、获取最新资讯的地方,这也衍生出了许多网红、主播等用户,他们会在直播系统源码平台发布高质量、受众多粉丝喜爱的短视频与直播,当然,直播系统......
  • Chromium 工程源码是如何测试的
    Chromium这样庞大的工程,涉及超多的模块依赖,如何保证代码质量?源码中随处可见xxx_unittest.cc和xxx_fuzzer.cc这样的文件,它们是如何组织的呢?项目的每一个Commit需要执行哪些测试,流程是什么?Chromium做了哪些基础的工作支持繁琐又重要的测试工作,我们是否可以借鉴用到自己的项目......
  • Spring源码分析(七)容器的扩展点(FactoryBean)
    在上篇文章中我已经对容器的第一个扩展点(BeanFactoryPostProcessor)做了一系列的介绍。其中主要介绍了Spring容器中BeanFactoryPostProcessor的执行流程,以及Spring自身利用了BeanFactoryPostProcessor完成了什么功能,对于一些细节问题可能说的不够仔细,但是当前阶段我想要做的......
  • 【源码】Vue.js 官方脚手架 create-vue 是怎么实现的?
    Vue.js官方脚手架create-vue是怎么实现的?摘要本文共分为四个部分,系统解析了vue.js官方脚手架create-vue的实现细节。第一部分主要是一些准备工作,如源码下载、项目组织结构分析、依赖分析、功能点分析等;第二部分分析了create-vue脚手架是如何执行的,执行文件的生成细节......
  • ubuntu 20.04源码编译安装ros2 gazebo及turtlebot3
    ros2gazebo安装gazebo11sudoapt-getinstallgazebo11gazebo-version//验证gazebo安装gazebo_ros_pkgsmkdir-p~/ros2_gazebo_ws/srccd~/ros2_gazebo_wswgethttps://raw.githubusercontent.com/ros-simulation/gazebo_ros_pkgs/ros2/gazebo_ros_pkgs.repos//显......
  • Spring源码分析(八)容器的扩展点(BeanPostProcessor)
    在前面两篇关于容器扩展的文章,我们已经完成了对BeanFactoryPostProcessor和FactoryBean的分析,对于BeanFactoryPostProcessor而言,它能让我们对容器中扫描出来的BeanDefinition做出修改以达到扩展的目的,而对于FactoryBean而言,它提供了一种特殊创建bean的手段,能让我们将一......
  • 基于微信小程序的助农电商系统设计与实现-计算机毕业设计源码+LW文档
    摘 要随着互联网技术的发展,传统的农产品销售迎来了机遇,我国是个农业大国,如何推广农产品的销售是农产品企业非常关注的事情。随着电子商务多元化的发展,各地方特产、农产品逐渐转移到线上销售。在互联网的帮助下,带动农产品企业打开销路,促进农产品可持续发展。同时,通过基于微信小......
  • C++编程语言在线学习系统-计算机毕业设计源码+LW文档
    摘要随着互联网技术的推进,我国高等教育逐渐实现信息化。许多精品C++编程语言在线学习系统的开发建设大大提高了教职工的教学效率,也为培养更多的高素质人才提供了途径。但是C++编程语言在线学习系统的发展也存在交互性不强、资源更新缓慢、教学形式单一等问题。因此,笔者设想开发一......
  • 旅行计划APP-计算机毕业设计源码+LW文档
    摘要随着社会经济的发展,各行业竞争激烈,年轻群体工作压力大,越来越多的人希望通过旅游来缓解压力。而传统的旅行社都是通过事先定制的线路和固定时间,没有个性化定制服务,不能满足现代用户的需求。对于此,开发旅行计划APP系统可以很好的解决用户个性化旅游的服务,通过系统查询各种景点信......