兩個項目中都使用了spring security安全框架,很多資料都是介紹spring security具體使用。今天我如果還是寫這些東西就顯得多余了,那么我從不同的角度來總結自己對這個框架的一些認識。
首先看看兩個疑惑,然后我會逐步解釋這兩個疑惑。
第一個疑惑,spring security框架是spring的子框架,我就非常好奇spring security和spring是如何融合起來,確切的說,spring security定義的對象如何納入spring ioc 容器中管理。研究到最后其實都是spring自身的一些知識,比如:自定義擴展xml schema,spring ioc啟動。
第二個疑惑,spring security如何攔截用戶的請求。這部分可以解讀spring security源碼可以得到答案。
徹底搞明白第一個疑惑之后,也許你以后自己寫一個框架,就可以很方便的整合到spring中去了。對于框架開發工程師來說,開發新的框架之后能整合spring是必須的事情了,畢竟spring給我們所帶來的好處是可想而知的。這也是我要徹底了解清楚原理的動力所在。廢話一堆,進入主題吧~~~~
第一個疑惑最后涉及到兩個方面的知識,spring ioc啟動和spring可擴展xml schema。spring ioc有兩個非常重要的概念,beanfactory和applicationContext,后者提供了更多更強的功能。為了避免過多的細節直接解讀beanfactory的讀取過程,xmlbeanfactory讀取xml文件會經歷如下兩個過程:1、通過resource接口讀取xml文件,轉換成document。 2、從document中解析出bean的配置。具體詳細過程請參照文章:
spring讀取xml配置源代碼分析(這篇文章一定要先看懂,不然后面很難繼續)。看過我介紹大家看的那篇文章之后,其實也有所了解spring擴展xml schema機制了。如果還不是很清楚再結合這篇文章:
基于Spring可擴展Schema提供自定義配置支持。感覺有點東拼西湊的,呵呵,主要怕以后自己忘記了,所以才寫篇blog。
第二個疑惑我們就看源代碼吧。
<filter-mapping>
<filter-name>jcaptchaFilter</filter-name>
<url-pattern>/j_spring_security_check</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>com.busyCity.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
web.xml中配置了
DelegatingFilterProxy,DelegatingFilterProxy調用FilterChainProxy的doFilter
public void doFilter(ServletRequest request, ServletResponse response)throws IOException, ServletException
{
if(currentPosition == additionalFilters.size())
{
if(FilterChainProxy.logger.isDebugEnabled())
FilterChainProxy.logger.debug((new StringBuilder()).append(fi.getRequestUrl()).append(" reached end of additional filter chain; proceeding with original chain").toString());
fi.getChain().doFilter(request, response);
} else
{
currentPosition++;
Filter nextFilter = (Filter)additionalFilters.get(currentPosition - 1);
if(FilterChainProxy.logger.isDebugEnabled())
FilterChainProxy.logger.debug((new StringBuilder()).append(fi.getRequestUrl()).append(" at position ").append(currentPosition).append(" of ").append(additionalFilters.size()).append(" in additional filter chain; firing Filter: '").append(nextFilter).append("'").toString());
nextFilter.doFilter(request, response, this);
}
}
這個方法就是循環調用我們用http命名空間配置的那些過濾器。然后根據不同的過濾器處理不同的內容。
我描述的都很簡單,主要原因是做個記錄,以后忘記了可以根據這個思路重新找到答案。不需要重新開始研究。呵呵。