相关文章推荐
犯傻的饺子  ·  文献到阿里巴巴北京总部调研时强调 ...·  9 月前    · 
还单身的红金鱼  ·  以案为鉴 | 编黑料炒舆论 ...·  1 年前    · 
温柔的跑步鞋  ·  《摩斯探长前传》 ...·  1 年前    · 
发呆的茴香  ·  【领克06 PHEV】领克_领克06 ...·  1 年前    · 
火爆的铅笔  ·  赤狐书生 - 720P|1080P高清下载 ...·  1 年前    · 
Code  ›  Spring Security过滤器的排序规则开发者社区
https://cloud.tencent.com/developer/article/2008327
有腹肌的火锅
1 年前
作者头像
码农小胖哥
0 篇文章

Spring Security过滤器的排序规则

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP
返回腾讯云官网
社区首页 > 专栏 > 码农小胖哥的码农生涯 > Spring Security过滤器的排序规则

Spring Security过滤器的排序规则

作者头像
码农小胖哥
发布 于 2022-05-22 09:46:41
734 0
发布 于 2022-05-22 09:46:41
举报

HttpSecurity 中的过滤器顺序是怎么维护的?我想很多开发者都对这个问题感兴趣。本篇我和大家一起探讨下这个问题。

HttpSecurity 包含了一个成员变量 FilterOrderRegistration ,这个类是一个内置过滤器注册表。至于这些过滤器的作用,不是本文介绍的重点,有兴趣可以去看看 FilterOrderRegistration 的源码。

内置过滤器的顺序

FilterOrderRegistration 维护了一个变量 filterToOrder ,它记录了类之间的顺序和上下之间的间隔步长。我们复制了一个 FilterOrderRegistration 来直观感受一下过滤器的顺序:

        CopyFilterOrderRegistration filterOrderRegistration = new CopyFilterOrderRegistration();
        // 获取内置过滤器  此方法并未提供
        Map<String, Integer> filterToOrder = filterOrderRegistration.getFilterToOrder();
        TreeMap<Integer, String> orderToFilter = new TreeMap<>();
        filterToOrder.forEach((name, order) -> orderToFilter.put(order,name));
        orderToFilter.forEach((order,name) -> System.out.println(" 顺序:" + order+" 类名:" + name ));

打印结果:

我们可以看得出内置过滤器之间的位置是相对固定的,除了第一个跟第二个步长为 200 外,其它步长为 100 。

❝内置过滤器并非一定会生效,仅仅是预置了它们的排位,需要通过 HttpSecurity 的 addFilterXXXX 系列方法显式添加才行。

注册过滤器的逻辑

FilterOrderRegistration 提供了一个 put 方法:

 void put(Class<? extends Filter> filter, int position) {
  String className = filter.getName();
        // 如果这个类已经注册就忽略
  if (this.filterToOrder.containsKey(className)) {
   return;
        // 如果没有注册就注册顺序。
  this.filterToOrder.put(className, position);

从这个方法我们可以得到几个结论:

  • 内置的 34 个过滤器是有固定序号的,不可被改变。
  • 新加入的过滤器的类全限定名是不能和内置过滤器重复的。
  • 新加入的过滤器的顺序是可以和内置过滤器的顺序重复的。

获取已注册过滤器的顺序值

FilterOrderRegistration 还提供了一个 getOrder 方法:

    Integer getOrder(Class<?> clazz) {
        // 如果类Class 或者 父类Class 名为空就返回null
        while (clazz != null) {
            Integer result = this.filterToOrder.get(clazz.getName());
            // 如果获取到顺序值就返回
            if (result != null) {
                return result;
            // 否则尝试去获取父类的顺序值
            clazz = clazz.getSuperclass();
        return null;

HttpSecurity维护过滤器的方法

接下来我们分析一下 HttpSecurity 维护过滤器的几个方法。

addFilterAtOffsetOf

addFilterAtOffsetOf 是一个 HttpSecurity 的内置私有方法。 Filter 是想要注册到 DefaultSecurityFilterChain 中的过滤器, offset 是向右的偏移值, registeredFilter 是已经注册到 FilterOrderRegistration 的过滤器,而且 registeredFilter 没有注册的话会空指针。

 private HttpSecurity addFilterAtOffsetOf(Filter filter, int offset, Class<? extends Filter> registeredFilter) {
        // 首先会根据registeredFilter的顺序和偏移值来计算filter的
  int order = this.filterOrders.getOrder(registeredFilter) + offset;
        // filter添加到集合中待排序
  this.filters.add(new OrderedFilter(filter, order));
        // filter注册到 FilterOrderRegistration
  this.filterOrders.put(filter.getClass(), order);
  return this;

❝务必记着 registeredFilter 一定是已注册入 FilterOrderRegistration 的 Filter 。

addFilter系列方法

这里以 addFilterAfter 为例。

 @Override
 public HttpSecurity addFilterAfter(Filter filter, Class<? extends Filter> afterFilter) {
  return addFilterAtOffsetOf(filter, 1, afterFilter);

addFilterAfter 是将 filter 的位置置于 afterFilter 后一位,假如 afterFilter 顺序值为 400 ,则 filter 顺序值为 401 。 addFilterBefore 和 addFilterAt 逻辑和 addFilterAfter 仅仅是偏移值的区别,这里不再赘述。

addFilter 的方法比较特殊:

 @Override
 public HttpSecurity addFilter(Filter filter) {
  Integer order = this.filterOrders.getOrder(filter.getClass());
  if (order == null) {
   throw new IllegalArgumentException("The Filter class " + filter.getClass().getName()
     + " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");
  this.filters.add(new OrderedFilter(filter, order));
  return this;
 
推荐文章
犯傻的饺子  ·  文献到阿里巴巴北京总部调研时强调 高质高效优化提升营商环境更好保障企业可持续发展
9 月前
还单身的红金鱼  ·  以案为鉴 | 编黑料炒舆论 诬告他人却扳倒自己--河北省纪委监委网站
1 年前
温柔的跑步鞋  ·  《摩斯探长前传》 新旧世界更迭中的失败者之歌_腾讯新闻
1 年前
发呆的茴香  ·  【领克06 PHEV】领克_领克06 PHEV报价_领克06 PHEV图片_参数_EV视界
1 年前
火爆的铅笔  ·  赤狐书生 - 720P|1080P高清下载 - 大陆电影 - BT天堂
1 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号