1. spring和spring security的集成,配置web.xml如下:
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring-security.xml </param-value> </context-param> <!-- Spring Security --> <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>
2. springSecurityFilterChain的來龍去脈
在org.springframework.security.config包里定義了該名稱:
/** External alias for FilterChainProxy bean, for use in web.xml files */ public static final String SPRING_SECURITY_FILTER_CHAIN = "springSecurityFilterChain";
使用springSecurityFilterChain的地方:HttpSecurityBeanDefinitionParser.java 該類建立
Http 安全體系:過濾器棧和受保護的url。
static void registerFilterChainProxyIfNecessary(ParserContext pc, Object source) { if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) { return; } // Not already registered, so register the list of filter chains and the FilterChainProxy BeanDefinition listFactoryBean = new RootBeanDefinition(ListFactoryBean.class); listFactoryBean.getPropertyValues().add("sourceList", new ManagedList()); pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, BeanIds.FILTER_CHAINS)); BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder.rootBeanDefinition(FilterChainProxy.class); fcpBldr.getRawBeanDefinition().setSource(source); fcpBldr.addConstructorArgReference(BeanIds.FILTER_CHAINS); fcpBldr.addPropertyValue("filterChainValidator", new RootBeanDefinition(DefaultFilterChainValidator.class)); BeanDefinition fcpBean = fcpBldr.getBeanDefinition(); pc.registerBeanComponent(new BeanComponentDefinition(fcpBean, BeanIds.FILTER_CHAIN_PROXY)); pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN); } }
從上面的代碼可以看出,springSecurityFilterChain是DelegatingFilterProxy的代理對象。
3.FilterChainProxy
代理一組spring管理的filter bean來處理request。從spring security2.0以后,除非你需要對filter chain的內容進行嚴格的控制,否則你就無需顯式的在context中配置一個FilterChainProxy。默認的<security:http />命名空間配置選項可以處理絕大部分應用場景。示例如下:
<http auto-config="true"> <remember-me key="xxx" token-validity-seconds="xxx" data-source-ref="dataSource"/> <form-login login-page="/login.jsp"/> <logout logout-success-url="/login.jsp"/> <intercept-url pattern="/*" access="ROLE_USER"/> </http>
通過在你的應用中的web.xml中增加一個名為DelegatingFilterProxy標准的spring聲明,就可以將FilterChaiProxy鏈接到servlet 容器的filter chain。
3.1 配置
從spring security 3.1版本,FilterChainProxy通過一組SecurityFilterChain實例來配置,每個SecurityFilterChain實例包含一個RequestMacher和一組匹配request的Filter。
大部分應用只需要包含一個簡單的filter chain,若你使用命名空間,你無需顯式的設置chain;若你需要一個精確的 控制,你可以使用<filter-chain>命名空間元素。它定義了一個urI匹配模式和一組逗號分隔的、應用到request和url匹配的filter。實例如下:
<bean id="myfilterChainProxy" class="org.springframework.security.util.FilterChainProxy"> <constructor-arg> <util:list> <security:filter-chain pattern="/do/not/filter*" filters="none"/> <security:filter-chain pattern="/**" filters="filter1,filter2,filter3"/> </util:list> </constructor-arg> </bean>
3.2 request處理
HttpFirewall實例用來驗證接收的request請求,並且創建一個新的包裝后的請求,這個新包裝的請求提供了和原請求一致的路徑值。
FilterChainProxy使用firewall實例來獲取應用到filter chain的request請求和response響應對象。當request請求通過security filter chain,將調用reset方法,此時將會返回servletPath和pathInfo的原始值,而不是security 模式匹配后的修改值。
3.3 Filter生命周期
注意,servlet容器中的filter生命周期和Ioc容器中的filter生命周期不一致。因此建議你使用Ioc容器而不是servlet容器來管理你增加到應用上下文的filter 的生命周期。
3.4 SecurityFilterChain
定義了一個filter chain,它能夠和HttpServletRequest進行匹配,匹配是為了決定是否需要應用到該request請求。
4. filters預覽
那么spring security有哪些filter呢?
SecurityFilters.java定義了默認的filter及其順序:
FIRST (Integer.MIN_VALUE), CHANNEL_FILTER, SECURITY_CONTEXT_FILTER, CONCURRENT_SESSION_FILTER, /** {@link WebAsyncManagerIntegrationFilter} */ WEB_ASYNC_MANAGER_FILTER, HEADERS_FILTER, CSRF_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, JAAS_API_SUPPORT_FILTER, REMEMBER_ME_FILTER, ANONYMOUS_FILTER, SESSION_MANAGEMENT_FILTER, EXCEPTION_TRANSLATION_FILTER, FILTER_SECURITY_INTERCEPTOR, SWITCH_USER_FILTER, LAST (Integer.MAX_VALUE); private static final int INTERVAL = 100;
測試:
public static void main(String[] args) { // TODO Auto-generated method stub System.out.println(SecurityFilters.CHANNEL_FILTER.getOrder()); System.out.println(SecurityFilters.SECURITY_CONTEXT_FILTER.getOrder()); System.out.println(SecurityFilters.CONCURRENT_SESSION_FILTER.getOrder()); }
結果如下:
100
200
300
以此類推:
默認的過濾器順序列表
order 過濾器名稱
100 ChannelProcessingFilter
200 ConcurrentSessionFilter
300 SecurityContextPersistenceFilter
400 LogoutFilter
500 X509AuthenticationFilter
600 RequestHeaderAuthenticationFilter
700 CasAuthenticationFilter
800 UsernamePasswordAuthenticationFilter
900 OpenIDAuthenticationFilter
1000 DefaultLoginPageGeneratingFilter
1100 DigestAuthenticationFilter
1200 BasicAuthenticationFilter
1300 RequestCacheAwareFilter
1400 SecurityContextHolderAwareRequestFilter
1500 RememberMeAuthenticationFilter
1600 AnonymousAuthenticationFilter
1700 SessionManagementFilter
1800 ExceptionTranslationFilter
1900 FilterSecurityInterceptor
2000 SwitchUserFilter
5. filters架構層次
6. 默認filter的創建