CAS實作原理:

認證流程分析:
1:使用者第一次通路受保護的應用。受保護的應用通過其中配置的統一認證過濾器隊請求進行過濾,未發現在session中有特定的使用者資訊,也未發現有ST參數。
2:應用系統将認定使用者第一次進入受保護的系統中,重定向到統一認證系統中特定的路徑。通常該路徑為 http:// 統一認證IP:端口/casserver/login
3:統一認證系統判斷使用者在統一認證系統中是否登入過。
4:如果沒有登入過,則将使用者定向到登入界面。
5:使用者在登入界面輸入使用者名和密碼等資訊,并進行送出。
6:統一認證系統驗證使用者送出的憑證是否正确,如果正确,生成cookie形式的TGT(ticket grant ticket)和一個ST(service ticket)。并通過重定向跳回到受保護的系統中。并且,将ST作為參數附加在URL後面。
7:進入受保護系統中,請求經由統一認證過濾器進行過濾,發現雖然在session中不存在特定的使用者資訊,但是存在ST票據。
8:有統一認證用戶端持有ST票據通過http請求,發送到統一認證端進行認證票據的有效性。
9:統一認證系統認證票據有效,相應使用者資訊到受保護系統。
10:受保護系統獲得使用者資訊,在session中設定特定的使用者資訊。傳回使用者通路資源。
了解了CAS實作單點登入的原理之後,我們就來看一下CAS伺服器端的整體結構:
分析web工程一般都是從web.xml檔案開始進行分析的。我們就先來看一下web.xml
首先是spring進行控制反轉控制的配置檔案。通常使用過spring的開發人員應該對spring會比較了解,這裡先不解釋,以後的分析中,會對spring的兩大特性IOC和AOP進行相應的分析。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-configuration/*.xml
/WEB-INF/deployerConfigContext.xml
</param-value>
</context-param>
第二部分是CAS的日志檔案的配置。這個方面以後将會作為一個知識點進行相對系統的分析。
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.xml</param-value>
</context-param>
<context-param>
<param-name>log4jExposeWebAppRoot</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>60000</param-value>
</context-param>
下面是CAS自身業務相關的重點了。
<filter>
<filter-name>CAS Client Info Logging Filter</filter-name>
<filter-class>com.github.inspektr.common.web.ClientInfoThreadLocalFilter</filter-class>
</filter>
該filter主要是對進入CAS自身的接入系統管理的請求進行過濾的。該過濾主要是采用springsecurity架構來處理的。這會在将來也會作為一個知識點進行重點分析。
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
該過濾器是對請求的字元編碼就行處理的過濾器。相信大家都會很熟悉。
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/services/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Client Info Logging Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
這裡是對日志初始化相關的監聽器。将會在日志部分重點分析。(其實不光是有日志,還有性能分析。)
<listener>
<listener-class>
org.springframework.web.util.Log4jConfigListener
</listener-class>
</listener>
<listener>
<listener-class>
org.jasig.cas.web.init.SafeContextLoaderListener
</listener-class>
</listener>
這裡是CAS進行統一認證的重點部分。和認證相關的請求都是由這個servlet進行處理的。
<servlet>
<servlet-name>cas</servlet-name>
<servlet-class>
org.jasig.cas.web.init.SafeDispatcherServlet
</servlet-class>
<init-param>
<param-name>publishContext</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/validate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/serviceValidate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/samlValidate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/proxy</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/proxyValidate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/CentralAuthenticationService</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/add.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/viewStatistics.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/logout.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/loggedOut.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/manage.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/edit.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/openid/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/deleteRegisteredService.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/authorizationFailure.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/403.html</url-pattern>
</servlet-mapping>
<session-config>
<!-- Default to 5minute session timeouts -->
<session-timeout>5</session-timeout>
</session-config>
<error-page>
<exception-type>org.springframework.context.ApplicationContextException</exception-type>
<location>/WEB-INF/view/jsp/brokenContext.jsp</location>
</error-page>
注意:一個filter和一個servlet是可以對多個路徑進行過濾的。是以,遇到一個servlet處理多個路徑的時候,最好不要嘗試攔截所有請求路徑,然後在servlet和filter中進行區分處理,這樣效率是會很低的。可以多些幾個filtermapping,多些幾個servletmapping。雖然讓web.xml看上去複雜很多,但效率會高出很多。