Spring Security 已经定义了一些 Filter,不管实际应用中你用到了哪些,它们应当保持如下顺序,来自SecurityFilters的枚举
在添加自定义的过滤器的时候,通过设置after/before/position来设置其过滤器对应的order值决定此过滤器在过滤器链中的位置如何
那么如何根据这些属性值进行排序呢?我们来看一下代码
List<OrderDecorator> buildCustomFilterList(Element element, ParserContext pc) {
List<Element> customFilterElts = DomUtils.getChildElementsByTagName(element, Elements.CUSTOM_FILTER);
List<OrderDecorator> customFilters = new ArrayList<OrderDecorator>();
final String ATT_AFTER = "after";
final String ATT_BEFORE = "before";
final String ATT_POSITION = "position";
for (Element elt: customFilterElts) {
String after = elt.getAttribute(ATT_AFTER);
String before = elt.getAttribute(ATT_BEFORE);
String position = elt.getAttribute(ATT_POSITION);
String ref = elt.getAttribute(ATT_REF);
if (!StringUtils.hasText(ref)) {
pc.getReaderContext().error("The '" + ATT_REF + "' attribute must be supplied", pc.extractSource(elt));
}
RuntimeBeanReference bean = new RuntimeBeanReference(ref);
if(WebConfigUtils.countNonEmpty(new String[] {after, before, position}) != 1) {
pc.getReaderContext().error("A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" +
ATT_POSITION + "' attribute must be supplied", pc.extractSource(elt));
}
if (StringUtils.hasText(position)) {
//如果设置了position属性值,则替换掉默认的过滤器
customFilters.add(new OrderDecorator(bean, SecurityFilters.valueOf(position)));
} else if (StringUtils.hasText(after)) {
SecurityFilters order = SecurityFilters.valueOf(after);
if (order == SecurityFilters.LAST) {
customFilters.add(new OrderDecorator(bean, SecurityFilters.LAST));
} else {
//如果设置成after,则order值在此基础上加1
customFilters.add(new OrderDecorator(bean, order.getOrder() + 1));
}
} else if (StringUtils.hasText(before)) {
SecurityFilters order = SecurityFilters.valueOf(before);
if (order == SecurityFilters.FIRST) {
customFilters.add(new OrderDecorator(bean, SecurityFilters.FIRST));
} else {
//如果设置成after,则order值在此基础上减1
customFilters.add(new OrderDecorator(bean, order.getOrder() - 1)); } } } return customFilters; }
最终在调用Collections.sort(unorderedFilterChain, new OrderComparator());时,根据order值进行排序
下面是OrderComparator的compare方法的实现
public int compare(Object o1, Object o2) {
boolean p1 = (o1 instanceof PriorityOrdered);
boolean p2 = (o2 instanceof PriorityOrdered);
if (p1 && !p2) {
return -1;
}
else if (p2 && !p1) {
return 1;
}
// Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation.
int i1 = getOrder(o1);
int i2 = getOrder(o2);
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}