實現機制
概括來講,是將認證信息放在Session中,當客戶端發起訪問時檢查Session中是否存在認證信息,以及認證信息中的權限是否滿足預期。
更具體地說,是通過Filter來攔截客戶端請求並進行判斷處理,使用的Filter鏈如下:
[
org.springframework.security.web.context.SecurityContextPersistenceFilter,
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter,
org.springframework.security.web.header.HeaderWriterFilter,
org.springframework.security.web.authentication.logout.LogoutFilter,
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter,
org.springframework.security.web.authentication.www.BasicAuthenticationFilter,
org.springframework.security.web.savedrequest.RequestCacheAwareFilter,
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter,
org.springframework.security.web.authentication.AnonymousAuthenticationFilter,
org.springframework.security.web.session.SessionManagementFilter,
org.springframework.security.web.access.ExceptionTranslationFilter,
org.springframework.security.web.access.intercept.FilterSecurityInterceptor
]
值得注意的是:這些Filter都是Spring Security框架中定義的,它們會被加載到Spring容器中,最終會被包裝到FilterChainProxy$.VirtualFilterChain
的additionalFilters
屬性中。
那麼這些Filter是如何生效的呢?
與普通的Sevlet Filter不同,這些Filter不需要在web.xml中明確配置,但是需要在web.xml中配置org.springframework.web.filter.DelegatingFilterProxy
作爲進入Spring Security框架的入口。
<!-- 集成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>
DelegatingFilterProxy
的執行路徑如下:
org.springframework.web.filter.DelegatingFilterProxy.doFilter()
->org.springframework.security.web.FilterChainProxy.doFilter() -> doFilterInternal()
->org.springframework.security.web.FilterChainProxy$.VirtualFilterChain.doFilter()
最後是在org.springframework.security.web.FilterChainProxy$.VirtualFilterChain.doFilter()
方法中依次取出additionalFilters
屬性中的Filter對象執行攔截操作。
認證流程
如上所述,Spring Security的認證實現都是通過Filter攔截來實現的,最終是在org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication()
方法中實現的。
具體的執行流程圖如下:
默認情況下,Spring Security處理登錄認證的URI地址爲/login
,且只支持POST
方法,這可以從UsernamePasswordAuthenticationFilter
的構造函數中得到確認。
public UsernamePasswordAuthenticationFilter() {
super(new AntPathRequestMatcher("/login", "POST"));
}
也就是說在<security:form-login>
中指定的login-processing-url
屬性實際上必須是/login
,同時也必須把自定義登錄頁面表單中的action
屬性也設置爲login
。
當然,Spring Security處理登錄認證的URI地址是可以修改的,如下所示在<security:form-login>
中修改:
<!--授權自定義登錄頁-->
<security:form-login login-processing-url="/lg">
特別注意:如果修改了默認認證地址URI,則必須同步修改自定義登錄頁面表單中的action
屬性值。