CAS認證原理分析(1)

一 配置實例

應用場景: cas 服務部署在192.168.7.115 ,是一個web 應用,訪問地址爲:https://cas.mycompany.com:8443/cas/ 。web1應用位於192.168.7.90 ,訪問地址爲:http://192.168.7.90:8081/web1 ,web2 應用位於192.168.7.90 ,訪問地址爲:http://192.168.7.90:8082/web2 。web1 和web2 經過cas 服務實現SSO 功能。瀏覽器位於本地localhost 。java


cas 服務器: 192.168.7.115  啓動8443 端口,需配置證書web


web1 : 192.168.7.90瀏覽器

hosts配置: 192.168.7.115  cas.mycompany.com緩存

 web.xml裏的配置:服務器

   <context-param>cookie

       <param-name>casServerUrlPrefix</param-name>session

       <param-value>https://cas.mycompany.com:8443/cas/</param-value>app

   </context-param>jsp

   <context-param>ide

       <param-name>serverName</param-name>

       <param-value>192.168.7.90:8081</param-value>

   </context-param>

   <filter>

       <filter-name>CAS Authentication Filter</filter-name>

<filter-class>

org.jasig.cas.client.authentication.AuthenticationFilter

</filter-class>

       <init-param>

          <param-name>casServerLoginUrl</param-name>

          <param-value>https://cas.mycompany.com:8443/cas/login</param-value>

       </init-param>

   </filter>

   <filter>

       <filter-name>CAS Validation Filter</filter-name>

       <filter-class>

org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter

</filter-class>

   </filter>

   <filter-mapping>

       <filter-name>CAS Authentication Filter</filter-name>

       <url-pattern>/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

       <filter-name>CAS Validation Filter</filter-name>

       <url-pattern>/*</url-pattern>

   </filter-mapping>


 JDK啓動參數需加上( 驗證CAS 服務器證書的須要) :

     -Djavax.net.ssl.trustStore=/home/yz/web1/conf/cas-client-trust-cert.jks

  -Djavax.net.ssl.trustStorePassword=casclient!@#


web2 : 192.168.7.90

hosts配置: 192.168.7.115  cas.mycompany.com

web.xml裏的配置:

   同web1 裏web.xml 的配置,只是serverName 屬性的值變成了192.168.7.90:8082


JDK 啓動參數需加上( 驗證CAS 服務器證書的須要) :

     -Djavax.net.ssl.trustStore=/home/yz/web2/conf/cas-client-trust-cert.jks

  -Djavax.net.ssl.trustStorePassword=casclient!@#


本地 :hosts 配置: 192.168.7.115  cas.mycompany.com


注:

1 casServerLoginUrl 參數的值是cas 服務器login 接口的值。web 應用裏的cas client 在認證的時候會redirect 到 cas 服務器,redirect 的url 就是casServerLoginUrl ,由於是redirect ,因此瀏覽器所在機器要配置cas 服務器的域名。

2 casServerUrlPrefix 參數的值是cas 服務的訪問地址。cas client 驗證ticket 的時候,要訪問cas 服務的/serviceValidate 接口,使用的url 就是${ casServerUrlPrefix }serviceValidate ,由於客戶web 應用要驗證cas 的證書,因此證書cn 字段的值必須和casServerUrlPrefix 裏設置的cas 服務器的域名保持一致,而且在web 應用的服務器上配置cas 服務的訪問域名。

2 serverName 參數,cas client 會用來生成service 參數,而且cas 服務器在認證經過、ticket 驗證經過後,會redirect到web 應用,redirect 的url 就是service 參數的值。serverName 參數能夠是IP ,也能夠是域名,只要保證瀏覽器能訪問到便可。

CAS 簡單介紹

CAS 官方網站: http://www.jasig.org/cas

CAS 的主要文檔:

http://www.ja-sig.org/wiki/display/CASUM/Home

http://www.jasig.org/cas/cas1-architecture

http://www.jasig.org/cas/cas2-architecture

http://www.jasig.org/cas/protocol/

http://www.ja-sig.org/wiki/display/CASUM/Demo

308795bb-c46c-35d7-bfc1-ed3568505310.jpg

CAS 官方網站上的介紹圖


主要原理:用戶第一次訪問一個CAS 服務的客戶web 應用時(訪問URL :http://192.168.7.90:8081/web1 ),部署在客戶web應用的cas AuthenticationFilter ,會截獲此請求,生成service 參數,而後redirect 到CAS 服務的login 接口,url爲https://cas:8443/cas/login?service=http%3A%2F%2F192.168.7.90%3A8081%2Fweb1%2F ,認證成功後,CAS 服務器會生成認證cookie ,寫入瀏覽器,同時將cookie 緩存到服務器本地,CAS 服務器還會根據service 參數生成ticket,ticket 會保存到服務器,也會加在url 後面,而後將請求redirect 回客戶web 應用,url 爲http://192.168.7.90:8081/web1/?ticket=ST-5-Sx6eyvj7cPPCfn0pMZuMwnbMvxpCBcNAIi6-20 。這時客戶端的AuthenticationFilter 看到ticket 參數後,會跳過,由其後面的TicketValidationFilter 處理,TicketValidationFilter 會利用httpclient 工具訪問cas 服務的/serviceValidate 接口, 將ticket、service 都傳到此接口,由此接口驗證ticket 的有效性,TicketValidationFilter 若是獲得驗證成功的消息,就會把用戶信息寫入web 應用的session 裏。至此爲止,SSO 會話就創建起來了,之後用戶在同一瀏覽器裏訪問此web 應用時,AuthenticationFilter 會在session 裏讀取到用戶信息,因此就不會去CAS 認證,若是在此瀏覽器裏訪問別的web 應用時,AuthenticationFilter 在session 裏讀取不到用戶信息,會去CAS 的login 接口認證,但這時CAS 會讀取到瀏覽器傳來的cookie ,因此CAS 不會要求用戶去登陸頁面登陸,只是會根據service 參數生成一個ticket ,而後再和web 應用作一個驗證ticket的交互而已。



CAS 客戶端 Filter 的處理邏輯

1 AuthenticationFilter

 if(url 中無ticket 參數 && session 中沒有TicketValidationFilter 置的assertion 對象){

    response.sendRedirect(cas 服務器的/login 接口);// 生成service 參數,添加到url 後面

 }

 else{

   不作處理

 }


2 TicketValidationFilter

 if(url 中有ticket 參數){

    經過httpclient 工具訪問cas 服務器的/serviceValidate 接口驗證ticket 的有效性,驗證失敗,顯示錯誤頁面,驗證成功,則生成標識用戶身份的assertion 對象,放入session 。

 }

 else{

   不作處理

 }


注:

1 AuthenticationFilter 在前,TicketValidationFilter 在後。

2 AuthenticationFilter :

  1 )url 中無ticket 參數,且session 中沒有TicketValidationFilter 置的assertion 對象,這種狀況說明用戶尚未認證,AuthenticationFilter 會去作認證處理;

  2 )url 中無ticket 參數,且session 中有TicketValidationFilter 置的assertion 對象,這種狀況說明用戶已經認證成功,AuthenticationFilter 不作處理;

  3 )url 中有ticket 參數,這種狀況說明用戶已經認證成功,但還須要經TicketValidationFilter 去驗證ticket,AuthenticationFilter不作處理。

3 TicketValidationFilter :只有客戶端調用cas 服務器的/login 接口, 併成功認證,redirect 回客戶端時,url 裏才帶有ticket 參數,在這種狀況下,TicketValidationFilter 才作處理。



CAS 服務端的處理邏輯

   CAS 服務端總共對外暴露了7 個接口,客戶端經過訪問這7 個接口與服務端交互,這7 個接口爲:/login 、/logout 、/validate、/serviceValidate 、/proxy 、/proxyValidate 、/CentralAuthenticationService 。/login 是認證接口,/logout 是退出接口,負責銷燬認證cookie,/validate 、/serviceValidate 是驗證ticket 用的接口,其中/validate 是CAS1.0 定義的,/serviceValidate是CAS2.0 定義的,其中/serviceValidate 返回xml 格式的數據,/proxy 、/proxyValidate 是支持代理認證功能的接口,/CentralAuthenticationService 接口用於和遠程的web services 交互。對於通常web 應用的單點登陸來說,/login、/logout 、/serviceValidate 這3 個接口已經能夠知足要求 。CAS 協議中已經對這些接口作了定義,連接爲:http://www.jasig.org/cas/protocol 。下面是我對CAS 各個接口實現的的詳細說明。


/login:

登陸流程這部分要考慮到不一樣種類用戶憑證的獲取方案,以及客戶應用傳來的service 、gateway 、renew 參數的不一樣取值組合,CAS 爲了實現流程的高度可配置性,採用了Spring Web Flow 技術。經過閱讀CAS 發佈包裏的login-webflow.xml 、cas-servlet.xml 、applicationContext.xml 這3 個文件,我找出 了登陸有關的全部組件,並畫出了它的處理流程圖。


d41dacbb-b056-35b0-81d9-740232aa6275.gif


                                                             CAS 默認的登陸處理流程


57708067-73c7-3a1c-b5c7-ec82000bd75c.gif

       第一次訪問Web 應用的流程走向


47c7aabd-b007-3515-a281-e85621bbe229.gif

              已經登陸web1 後,訪問web1 的資源(web1 沒有啓動session ),或訪問web2 的資源


注:

1 : InitialFlowSetupAction: 是流程的入口。用 request.getContextPath() 的值來設置 cookie 的 Path 值, Cookie 的 path 值是在配置文件裏定義的,但這個 Action 負責將 request.getContextPath() 的值設置爲 Cookie 的 path 值,這是在 cas 部署環境改變的狀況下,靈活地設置 cookie path 的方式;把 cookie 的值以及 service 參數的值放入 requestContext 的 flowscope 裏。

2 : GenerateServiceTicketAction 此 Action 負責根據 service 、 GTC cookie 值生成 ServiceTicket 對象, ServiceTicket 的 ID就是返回給客戶應用的 ticket 參數,若是成功建立 ServiceTicket ,則轉發到 WarnAction ,若是建立失敗,且 gateway 參數爲true ,則直接 redirect 到客戶應用, 不然則須要從新認證。

3 : viewLoginForm 這是登陸頁面, CAS 在此收集用戶憑證。 CAS 提供的默認實現是 /WEB-INF/view/jsp/simple/ui/casLoginView.jsp 。

4 : bindAndValidate 對應 AuthenticationViaFormAction 的 doBind 方法,該方法負責蒐集登陸頁面上用戶錄入的憑證信息(用戶名、密碼等),而後把這些信息封裝到 CAS 內部的 Credentials 對象中。用戶在 casLoginView.jsp 頁面上點擊提交後,會觸發此方法。

5:submit   對應 AuthenticationViaFormAction 的 submit 方法 , 若是 doBind 方法成功執行完, 則觸發 submit 方法,此方法負責調用 centralAuthenticationService 的      grantServiceTicket 方法,完成認證工做,若是認證成功,則生成TicketGrantingTicket 對象,放在緩存裏, TicketGrantingTicket 的 ID 就是 TGC Cookie 的 value 值。

6 : warn  CAS 提供了一個功能:用戶在一個 web 應用中跳到另外一個 web 應用時, CAS 能夠跳轉到一個提示頁面,該頁面提示用戶要離開一個應用進入另外一個應用,可讓用戶本身選擇。用戶在登陸頁面 viewLoginForm 上選中了 id=」warn」 的複選框,才能開啓這個功能。

WarnAction 就檢查用戶有沒有開啓這個功能,若是開啓了,則轉發到showWarnView, 若是沒開啓,則直接redirect 到客戶應用。

7 :SendTicketGrantingTicketAction 此Action 負責爲response 生成TGC Cookie ,cookie 的值就是AuthenticationViaFormAction 的 submit 方法生成的 TicketGrantingTicket 對象的 ID 。

8 : viewGenerateLoginSuccess 這是 CAS 的認證成功頁面。



/logout: 對應實現類 org.jasig.cas.web.LogoutController )

  處理邏輯:  

       1) removeCookie

      2) 在服務端刪除TicketGrantingTicket 對象(此對象封裝了cookie 的value 值)

      3 )redirect 到退出頁面,有2 種選擇:

         if(LogoutController 的followServiceRedirects 屬性爲true 值,且url 裏的service 參數非空){

               redirect 到 sevice 參數標識的url

            }

         else{

            redirect 到內置的casLogoutView (cas/WEB-INF/view/jsp/default/ui/casLogoutView.jsp ),若是url 裏有url 參數,則此url 參數標識的連接會顯示在casLogoutView 頁面上。

          }

/serviceValidate: (對應實現類 org.jasig.cas.web.ServiceValidateController )

    處理邏輯:  

 若是service 參數爲空或ticket 參數爲空,則轉發到failureView (/WEB-INF/view/jsp/default/protocol/2.0/casServiceValidationFailure.jsp )

   驗證ticket 。以ticket 爲參數,去緩存裏找ServiceTicketImpl 對象,若是能找到,且沒有過時,且ServiceTicketImpl 對象對應的service 屬性和service 參數對應,則驗證經過,驗證經過後,請求轉發至casServiceSuccessView (cas/WEB-INF/view/jsp/default/protocol/2.0/casServiceValidationSuccess.jsp ),驗證不經過,則轉發到failureView 。


四 認證相關的概念及流程

概念

  • Credentials 用戶提供的用於登陸用的憑據信息,如用戶名/ 密碼、證書、IP 地址、Cookie 值等。好比 UsernamePasswordCredentials ,封裝的是用戶名和密碼。CAS 進行認證的第一步,就是把從UI 或request 對象裏取到的用戶憑據封裝成Credentials 對象,而後交給認證管理器去認證。

  • AuthenticationHandler 認證Handler, 每種AuthenticationHandler 只能處理一種Credentials ,如AbstractUsernamePasswordAuthenticationHandler 只負責處理 U sernamePasswordCredentials 。

  • Principal 封裝用戶標識,好比 SimplePrincipal, 只是封裝了用戶名。認證成功後, credentialsToPrincipalResolvers 負責由 Credentials 生成 Principal 對象。

  • CredentialsToPrincipalResolvers 負責由 Credentials 生成 Principal 對象,每種 CredentialsToPrincipalResolvers 只處理 一種Credentials ,好比 UsernamePasswordCredentialsToPrincipalResolver 負責從 U sernamePasswordCredentials中取出用戶名,而後將其賦給生成的 SimplePrincipal 的 ID 屬性。

  • AuthenticationMetaDataPopulators 負責將 Credentials 的一些屬性賦值給 Authentication 的 attributes 屬性。

  • Authentication   Authentication是認證管理器的最終處理結果, Authentication 封裝了 Principal ,認證時間,及其餘一些屬性(可能來自 Credentials )。

  • AuthenticationManager 認證管理器獲得 Credentials 對象後,負責調度AuthenticationHandler 去完成認證工做,最後返回的結果是 Authentication 對象。

  • CentralAuthenticationService  CAS 的服務類,對 Web 層提供了一些方法。該類還負責調用 AuthenticationManager 完成認證邏輯

序列圖


530fabe8-602e-38b6-b01b-5dda3227f6f5.jpg

CAS 認證處理序列圖

類圖



8cf00e06-7281-30ed-b305-f88484d7ebc9.jpg

CAS 認證類圖

相關文章
相關標籤/搜索