Spring Security3源码分析-Filter链排序分析

通过前面Spring Security提供的各种Filter的分析,大体上知道每个Filter具体的用途了。
Spring Security一共提供了20个Filter,我目前只分析了13个(如果http的auto-config="true",那默认的filter列表都包含在这13个里面了),另外7个在后面的源码分析中碰到时会逐个讲解。
在分析http标签时,已经提到filter排序的问题了,但是没有深入。

现在再回头看filter是如何排序的。下面的代码片段截取自HttpSecurityBeanDefinitionParser类,

//定义未排序filter集合。该集合中的对象为OrderDecorator实例。
List<OrderDecorator> unorderedFilterChain = new ArrayList<OrderDecorator>();
//添加http、认证相关的filter集合
unorderedFilterChain.addAll(httpBldr.getFilters());
unorderedFilterChain.addAll(authBldr.getFilters());
//定义RequestCacheAwareFilter过滤器,并添加到unorderedFilterChain中
BeanDefinition requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class);
requestCacheAwareFilter.getPropertyValues().addPropertyValue("requestCache", authBldr.getRequestCache());
unorderedFilterChain.add(new OrderDecorator(requestCacheAwareFilter, REQUEST_CACHE_FILTER));
//添加自定义filter
unorderedFilterChain.addAll(buildCustomFilterList(element, pc));
//根据排序规则进行排序
Collections.sort(unorderedFilterChain, new OrderComparator());
//检查每个filter与前一个filter的位置是否相同
//这里的检查主要是防止自定义filter直接配置position属性,造成与默认的filter产生order冲突
checkFilterChainOrder(unorderedFilterChain, pc, source);
//重新定义filterChain,把经过排序的filter依次添加到filterChain集合中
List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();

for (OrderDecorator od : unorderedFilterChain) {
filterChain.add(od.bean);
}

细心的同学会发现httpBldr.getFilters()、authBldr.getFilters()两个方法返回的就是OrderDecorator对象的集合列表。并且OrderDecorator对象已经将filter与SecurityFilters中的order关联了起来

unorderedFilterChain.addAll(httpBldr.getFilters());
unorderedFilterChain.addAll(authBldr.getFilters());


顺便看一下创建自定义过滤器部分

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";
//循环自定义标签列表custom-filter
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));
}
//如果指定了position,直接将filter与order产生关联关系
if (StringUtils.hasText(position)) {
customFilters.add(new OrderDecorator(bean, SecurityFilters.valueOf(position)));
//如果指定了after,将filter与after值加一产生关联关系
} else if (StringUtils.hasText(after)) {
SecurityFilters order = SecurityFilters.valueOf(after);
if (order == SecurityFilters.LAST) {
customFilters.add(new OrderDecorator(bean, SecurityFilters.LAST));
} else {
customFilters.add(new OrderDecorator(bean, order.getOrder() + 1));
}
//如果指定了before,将filter与before-1产生关联关系
} else if (StringUtils.hasText(before)) {
SecurityFilters order = SecurityFilters.valueOf(before);
if (order == SecurityFilters.FIRST) {
customFilters.add(new OrderDecorator(bean, SecurityFilters.FIRST));
} else {
customFilters.add(new OrderDecorator(bean, order.getOrder() - 1));
}
}
}

return customFilters;
}


这里用到三个重要的与排序相关的类及枚举,分别是OrderDecorator、OrderComparator以及SecurityFilters枚举
首先看SecurityFilters枚举定义

enum SecurityFilters {
FIRST (Integer.MIN_VALUE),
//order=100
CHANNEL_FILTER,
//order=200
CONCURRENT_SESSION_FILTER,
//依次递增……
SECURITY_CONTEXT_FILTER,
LOGOUT_FILTER,
X509_FILTER,
PRE_AUTH_FILTER,
CAS_FILTER,
FORM_LOGIN_FILTER,
OPENID_FILTER,
LOGIN_PAGE_FILTER,
DIGEST_AUTH_FILTER,
BASIC_AUTH_FILTER,
REQUEST_CACHE_FILTER,
SERVLET_API_SUPPORT_FILTER,
REMEMBER_ME_FILTER,
ANONYMOUS_FILTER,
SESSION_MANAGEMENT_FILTER,
EXCEPTION_TRANSLATION_FILTER,
FILTER_SECURITY_INTERCEPTOR,
SWITCH_USER_FILTER,
LAST (Integer.MAX_VALUE);
//这里设置100,主要给自定义过滤器提供after、before的预留位置
//也就是说,在某个默认的过滤器前后只能自定义99个过滤器,虽然可能性几乎为0
private static final int INTERVAL = 100;
private final int order;
//返回的order值=序号*间隔100
private SecurityFilters() {
order = ordinal() * INTERVAL;
}

private SecurityFilters(int order) {
this.order = order;
}
//主要通过该方法返回Filter的位置
public int getOrder() {
return order;
}
}

由此可见,该类维护了Spring Security中每个filter的顺序

接着看OrderDecorator类。这个类实现org.springframework.core.Ordered接口

class OrderDecorator implements Ordered {
BeanMetadataElement bean;
int order;
//构造函数传递两个参数1.bean定义;2.filter在链中的位置
public OrderDecorator(BeanMetadataElement bean, SecurityFilters filterOrder) {
this.bean = bean;
this.order = filterOrder.getOrder();
}

public OrderDecorator(BeanMetadataElement bean, int order) {
this.bean = bean;
this.order = order;
}
//实现接口方法getOrder
public int getOrder() {
return order;
}

public String toString() {
return bean + ", order = " + order;
}
}

OrderComparator类的路径是org.springframework.core.OrderComparator,实际上是spring core包的一个比较器,可以顺便看下OrderComparator源码。下面截取的只是部分核心代码

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;
}
//前面几行代码主要针对PriorityOrdered,这里不做分析

//分别获取Ordered接口实现类的getOrder方法得到order值
int i1 = getOrder(o1);
int i2 = getOrder(o2);
//对得到的order进行比较
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}
//获取Ordered接口的实现类,获取getOrder值
protected int getOrder(Object obj) {
return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : Ordered.LOWEST_PRECEDENCE);
}


通过以上的分析,可以总结如下
[color=red]
1.由SecurityFilters维持位置order
2.由OrderDecorator维持filter与order的对应关系
3.由OrderComparator负责比较OrderDecorator的先后顺序
[/color]

附上默认的过滤器顺序列表
[table]
|order|过滤器名称|
|100|ChannelProcessingFilter|
|200|[color=red]ConcurrentSessionFilter[/color]|
|300|[color=red]SecurityContextPersistenceFilter[/color]|
|400|[color=red]LogoutFilter[/color]|
|500|X509AuthenticationFilter|
|600|RequestHeaderAuthenticationFilter|
|700|CasAuthenticationFilter|
|800|[color=red]UsernamePasswordAuthenticationFilter[/color]|
|900|OpenIDAuthenticationFilter|
|1000|[color=red]DefaultLoginPageGeneratingFilter[/color]|
|1100|DigestAuthenticationFilter|
|1200|[color=red]BasicAuthenticationFilter[/color]|
|1300|[color=red]RequestCacheAwareFilter[/color]|
|1400|[color=red]SecurityContextHolderAwareRequestFilter[/color]|
|1500|[color=red]RememberMeAuthenticationFilter[/color]|
|1600|[color=red]AnonymousAuthenticationFilter[/color]|
|1700|[color=red]SessionManagementFilter[/color]|
|1800|[color=red]ExceptionTranslationFilter[/color]|
|1900|[color=red]FilterSecurityInterceptor[/color]|
|2000|SwitchUserFilter|
[/table]
以上标注红色的都已经分析完毕
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值