概述
用过Spring Security XML配置方式的肯定属性下面的代码:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
类似的Shiro在配置的时候,也会有一样的代码:
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Spring Web Filter
Spring Web对将常见的Servlet Filter的场景做了简单的增强和封装。GenericFilterBean和CompositeFilter是Spring Web Filter的两个顶级实现。GenericFilterBean不仅实现了Servlet Filter的Filter接口,还实现了一大堆Spring IOC 的接口,如下:
public abstract class GenericFilterBean implements Filter, BeanNameAware, EnvironmentAware,
EnvironmentCapable, ServletContextAware, InitializingBean, DisposableBean
由此实现了Spring 容器的信息的注入和生命周期的被管理的功能;
CompositeFilter是用来组合多个Filter的工具类;
GenericFilterBean有一个子类是OncePerRequestFilter,看名字就知道了,其实现了一个Request请求,只调用一次的功能(如果不明白,可以看下Filter的调用过程)。实际上,Spring Web Filter包下面的大部分具体的实现都扩展自OncePerRequestFilter。比如说CharacterEncodingFilter、RequestLoggingFilter、CorsFilter、ForwardedHeaderFilter、HiddenHttpMethodFilter、HttpPutFormContentFilter、RequestContextFilter、ShallowEtagHeaderFilter;
DelegatingFilterProxy继承自GenericFilterBean,这也是一个工具类。他可以作为Spring管理的Filter的对象的代理。最开始的Spring Security和Shiro的配置就是用到了这个类。
Spring Security与DelegatingFilterProxy
在Spring Security Web的context包下面有一个Spring WebApplicationInitializer接口的实现AbstractSecurityWebApplicationInitializer;在其onStartup方法中会调用如下的私有方法:
public static final String DEFAULT_FILTER_NAME = "springSecurityFilterChain";
/**
* Registers the springSecurityFilterChain
* @param servletContext the {@link ServletContext}
*/
private void insertSpringSecurityFilterChain(ServletContext servletContext) {
String filterName = DEFAULT_FILTER_NAME;
DelegatingFilterProxy springSecurityFilterChain = new DelegatingFilterProxy(
filterName);
String contextAttribute = getWebApplicationContextAttribute();
if (contextAttribute != null) {
springSecurityFilterChain.setContextAttribute(contextAttribute);
}
registerFilter(servletContext, true, filterName, springSecurityFilterChain);
}
将名为springSecurityFilterChain的bean用DelegatingFilterProxy 包装之后,动态注册到Servlet容器中;跟上边xml的配置是一样的功能。
SecurityFilterChain是Spring Security Filter调用链。调用链可以像Spring MVC 路由到某个Controller那样提供非常精细丰富的配置。
Shiro的使用方式是一模一样的,感兴趣的同学可以去看看Shiro的相关实现。