Spring Security的内置过滤器是如何维护的

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

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

内置过滤器的滤器顺序

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

CopyFilterOrderRegistration filterOrderRegistration = new CopyFilterOrderRegistration();

// 获取内置过滤器 此方法并未提供

MapfilterToOrder = filterOrderRegistration.getFilterToOrder();

TreeMaporderToFilter = 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 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 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 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;

}

filter必须是已经注册到FilterOrderRegistration的Filter,这意味着它可能是内置的Filter,也可能是先前通过addFilterBefore、addFilterAt或者addFilterAfter注册的非内置Filter。

问题来了

之前看到一个问题,如果HttpSecurity注册两个重复序号的Filter会是怎么样的服务器托管顺序呢?我们先来看下排序的机制:

// filters

private Listfilters = new ArrayList<>();

//排序

this.filters.sort(OrderComparator.INSTANCE);

看了下OrderComparator源码,其实还是通过数字的自然排序,数字越小越靠前。如果数字相同,索引越小越靠前。也就是同样的序号,谁先add到filters谁就越靠前。

应用开发
上一篇:为什么起域名意义非凡?起域名有什么名堂?
下一篇:国际域名转移的费用和处理步骤是什么?