Spring Security3源码分析-Filter链排序分析
通过前面SpringSecurity提供的各种Filter的分析,大体上知道每个Filter具体的用途了。
SpringSecurity一共提供了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; } }
由此可见,该类维护了SpringSecurity中每个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,实际上是springcore包的一个比较器,可以顺便看下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); }
通过以上的分析,可以总结如下
1.由SecurityFilters维持位置order
2.由OrderDecorator维持filter与order的对应关系
3.由OrderComparator负责比较OrderDecorator的先后顺序
附上默认的过滤器顺序列表
order过滤器名称100ChannelProcessingFilter200ConcurrentSessionFilter300SecurityContextPersistenceFilter400LogoutFilter500X509AuthenticationFilter600RequestHeaderAuthenticationFilter700CasAuthenticationFilter800UsernamePasswordAuthenticationFilter900OpenIDAuthenticationFilter1000DefaultLoginPageGeneratingFilter1100DigestAuthenticationFilter1200BasicAuthenticationFilter1300RequestCacheAwareFilter1400SecurityContextHolderAwareRequestFilter1500RememberMeAuthenticationFilter1600AnonymousAuthenticationFilter1700SessionManagementFilter1800ExceptionTranslationFilter1900FilterSecurityInterceptor2000SwitchUserFilter
以上标注红色的都已经分析完毕