CAS實現SSO單點登錄


https://blog.csdn.net/u011872945/article/details/81044124

 

CAS 介紹

CAS 是 Yale 大學發起的一個開源項目,旨在為 Web 應用系統提供一種可靠的單點登錄方法,CAS 在 2004 年 12 月正式成為 JA-SIG 的一個項目。CAS 具有以下特點:

  • 開源的企業級單點登錄解決方案。
  • CAS Server 為需要獨立部署的 Web 應用。
  • CAS Client 支持非常多的客戶端(這里指單點登錄系統中的各個 Web 應用),包括 Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等。

CAS 原理和協議

從結構上看,CAS 包含兩個部分: CAS Server 和 CAS Client。CAS Server 需要獨立部署,主要負責對用戶的認證工作;CAS Client 負責處理對客戶端受保護資源的訪問請求,需要登錄時,重定向到 CAS Server。圖1 是 CAS 最基本的協議過程:

圖 1. CAS 基礎協議

CAS 基礎協議

CAS Client 與受保護的客戶端應用部署在一起,以 Filter 方式保護受保護的資源。對於訪問受保護資源的每個 Web 請求,CAS Client 會分析該請求的 Http 請求中是否包Service Ticket,如果沒有,則說明當前用戶尚未登錄,於是將請求重定向到指定好的 CAS Server 登錄地址,並傳遞 Service (也就是要訪問的目的資源地址),以便登錄成功過后轉回該地址。用戶在第 3 步中輸入認證信息,如果登錄成功,CAS Server 隨機產生一個相當長度、唯一、不可偽造的 Service Ticket,並緩存以待將來驗證,之后系統自動重定向到Service 所在地址,並為客戶端瀏覽器設置一個 Ticket Granted Cookie(TGC),CAS Client 在拿到 Service 和新產生的 Ticket 過后,在第 5,6 步中與 CAS Server 進行身份合適,以確保 Service Ticket 的合法性。

在該協議中,所有與 CAS 的交互均采用 SSL 協議,確保,ST 和 TGC 的安全性。協議工作過程中會有 2 次重定向的過程,但是 CAS Client 與 CAS Server 之間進行 Ticket 驗證的過程對於用戶是透明的。

另外,CAS 協議中還提供了 Proxy (代理)模式,以適應更加高級、復雜的應用場景,具體介紹可以參考 CAS 官方網站上的相關文檔。

一、CAS 原理介紹

 

訪問流程圖

 

主要原理:用戶第一次訪問一個CAS 服務的客戶web 應用時(訪問URL :http://192.168.1.90:8081/web1 ),部署在客戶web 應用的cas AuthenticationFilter ,會截獲此請求,生成service 參數,然后redirect 到CAS 服務的login 接口,url為https://cas:8443/cas/login?service=http%3A%2F%2F192.168.1.90%3A8081%2Fweb1%2F ,認證成功后,CAS 服務器會生成認證cookie ,寫入瀏覽器,同時將cookie 緩存到服務器本地,CAS 服務器還會根據service 參數生成ticket,ticket 會保存到服務器,也會加在url 后面,然后將請求redirect 回客戶web 應用,url 為http://192.168.1.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 服務端的處理邏輯

CAS 服務端總共對外定義了9 個接口,客戶端通過訪問這9 個接口與服務端交互,這9個接口為:

接口

說明

備注

/login

認證接口

 

/logout

退出接口,負責銷毀認證cookie

 

/validate

驗證ticket 用的接口,CAS1.0 定義

 

/serviceValidate

驗證ticket 用的接口,CAS2.0 定義,返回xml 格式的數據

 

/proxy

支持代理認證功能的接口

 

/proxyValidate

支持代理認證功能的接口

 

/CentralAuthenticationService

用於和遠程的web services 交互

 

/remoteLogin(新增)

認證接口

 

/directLogin(新增)

認證接口

 

 

詳細說明:

 /login:

登錄流程這部分要考慮到不同種類用戶憑證的獲取方案,以及客戶應用傳來的service 、gateway 、renew 參數的不同取值組合,CAS 為了實現流程的高度可配置性,采用了Spring Web Flow 技術。通過CAS 發布包里的login-webflow.xml 、cas-servlet.xml 、applicationContext.xml 這3 個文件,找出 了登錄有關的所有組件,畫出處理流程圖。

 

CAS 默認的登錄處理流程

 

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

 

已經登錄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 完成認證邏輯

 

序列圖

 

 

類圖

 

 

四、Ticket介紹

CAS的核心就是其Ticket,及其在Ticket之上的一系列處理操作。CAS的主要票據有TGT、ST、PGT、PGTIOU、PT,其中TGT、ST是CAS1.0協議中就有的票據,PGT、PGTIOU、PT是CAS2.0協議中有的票據。

 

一 名詞解釋

  • TGT(Ticket Grangting Ticket)

TGT是CAS為用戶簽發的登錄票據,擁有了TGT,用戶就可以證明自己在CAS成功登錄過。TGT封裝了Cookie值以及此Cookie值對應的用戶信息。用戶在CAS認證成功后,CAS生成cookie,寫入瀏覽器,同時生成一個TGT對象,放入自己的緩存,TGT對象的ID就是cookie的值。當HTTP再次請求到來時,如果傳過來的有CAS生成的cookie,則CAS以此cookie值為key查詢緩存中有無TGT ,如果有的話,則說明用戶之前登錄過,如果沒有,則用戶需要重新登錄。

 

  • ST(Service Ticket)

ST是CAS為用戶簽發的訪問某一service的票據。用戶訪問service時,service發現用戶沒有ST,則要求用戶去CAS獲取ST。用戶向CAS發出獲取ST的請求,如果用戶的請求中包含cookie,則CAS會以此cookie值為key查詢緩存中有無TGT,如果存在TGT,則用此TGT簽發一個ST,返回給用戶。用戶憑借ST去訪問service,service拿ST去CAS驗證,驗證通過后,允許用戶訪問資源。

 

  • PGT(Proxy Granting Ticket)

Proxy Service的代理憑據。用戶通過CAS成功登錄某一Proxy Service后,CAS生成一個PGT對象,緩存在CAS本地,同時將PGT的值(一個UUID字符串)回傳給Proxy Service,並保存在Proxy Service里。Proxy Service拿到PGT后,就可以為Target Service(back-end service)做代理,為其申請PT。

 

  • PGTIOU(Proxy Granting Ticket IOU)

PGTIOU是CAS協議中定義的一種附加票據,它增強了傳輸、獲取PGT的安全性。
PGT的傳輸與獲取的過程:Proxy Service調用CAS的serviceValidate接口驗證ST成功后,CAS首先會訪問pgtUrl指向的https url,將生成的 PGT及PGTIOU傳輸給proxy service,proxy service會以PGTIOU為key,PGT為value,將其存儲在Map中;然后CAS會生成驗證ST成功的xml消息,返回給Proxy Service,xml消息中含有PGTIOU,proxy service收到Xml消息后,會從中解析出PGTIOU的值,然后以其為key,在map中找出PGT的值,賦值給代表用戶信息的Assertion對象的pgtId,同時在map中將其刪除。

 

  • PT(Proxy Ticket)

PT是用戶訪問Target Service(back-end service)的票據。如果用戶訪問的是一個Web應用,則Web應用會要求瀏覽器提供ST,瀏覽器就會用cookie去CAS獲取一個ST,然后就可以訪問這個Web應用了。如果用戶訪問的不是一個Web應用,而是一個C/S結構的應用,因為C/S結構的應用得不到cookie,所以用戶不能自己去CAS獲取ST,而是通過訪問proxy service的接口,憑借proxy service的PGT去獲取一個PT,然后才能訪問到此應用。

 

二 代碼解析

 

CAS Ticket類圖

 

  • TicketGrantingTicket 的 grantServiceTicket方法

方法聲明:public synchronized ServiceTicket grantServiceTicket(final String id,final Service service, final ExpirationPolicy expirationPolicy, final boolean credentialsProvided)

方法描述:

 1:生成SerivceTicketImpl

 2:更新屬性:

this.previousLastTimeUsed = this.lastTimeUsed;

   this.lastTimeUsed = System.currentTimeMillis();

   this.countOfUses++;

 3:給service對象的principal屬性賦值

 4:將service對象放入map services

 

  • ServiceTicket 的 grantTicketGrantingTicket方法

方法聲明:

public TicketGrantingTicket grantTicketGrantingTicket(final String id, final Authentication authentication,final ExpirationPolicy expirationPolicy)

方法描述:在CAS3.3對CAS2.0協議的實現中,PGT是由ST簽發的,調用的就是ServiceTicket的grantTicketGrantingTicket方法。方法返回的TicketGrantingTicket對象,表征的是一個PGT對象,其中的ticketGrantingTicket屬性的值是簽發ST的TGT對象。

 

  • TicketGrantingTicket 的 expire方法

方法聲明:void expire()

方法描述:

在CAS的logout接口實現中,要調用TGT對象的expire方法,然后會在緩存中清除此TGT對象。

expire方法的內容:循環遍歷 services 中的Service對象,調用其logoutOfService方法。具體Service實現類中的logoutOfService方法的實現,要通知具體的應用,客戶要退出。

 

三、TGT、ST、PGT、PT關系

1:ST是TGT簽發的。用戶在CAS上認證成功后,CAS生成TGT,用TGT簽發一個ST,ST的ticketGrantingTicket屬性值是TGT對象,然后把ST的值redirect到客戶應用。

 

2:PGT是ST簽發的。用戶憑借ST去訪問Proxy service,Proxy service去CAS驗證ST(同時傳遞PgtUrl參數給CAS),如果ST驗證成功,則CAS用ST簽發一個PGT,PGT對象里的ticketGrantingTicket是簽發ST的TGT對象。

 

3:PT是PGT簽發的。Proxy service代理back-end service去CAS獲取PT的時候,CAS根據傳來的pgt參數,獲取到PGT對象,然后調用其grantServiceTicket方法,生成一個PT對象。

 

TGT、ST、PGT、PT之間的關聯關系

 

 

 

 

CAS CLIENT篇

CASFilter 參數說明:

 

參數

是否必須

說明

com.olymtech.cas.client.filter.loginUrl

指定 CAS 提供登錄頁面的 URL

com.olymtech.cas.client.filter.validateUrl

指定 CAS 提供 service ticket 或 proxy ticket 驗證服務的 URL

com.olymtech.cas.client.filter.serverName

指定客戶端的域名和端口,是指客戶端應用所在機器而不是 CAS Server 所在機器,該參數或 serviceUrl 至少有一個必須指定

com.olymtech.cas.client.filter.serviceUrl

該參數指定過后將覆蓋 serverName 參數,成為登錄成功過后重定向的目的地址

com.olymtech.cas.client.filter.wrapRequest

如果指定為 true,那么 CASFilter 將重新包裝 HttpRequest,並且使 getRemoteUser() 方法返回當前登錄用戶的用戶名

com.olymtech.cas.client.filter.noFilter

設置不過濾的路徑,語法如下:/name1/,/name2,

com.olymtech.cas.client.filter.proxyCallbackUrl

用於當前應用需要作為其他服務的代理(proxy)時獲取 Proxy Granting Ticket 的地址

com.olymtech.cas.client.filter.authorizedProxy

用於允許當前應用從代理處獲取 proxy tickets,該參數接受以空格分隔開的多個 proxy URLs,但實際使用只需要一個成功即可。當指定該參數過后,需要修改 validateUrl 到 proxyValidate,而不再是 serviceValidate

com.olymtech.cas.client.filter.renew

如果指定為 true,那么受保護的資源每次被訪問時均要求用戶重新進行驗證,而不管之前是否已經通過

com.olymtech.cas.client.filter.gateway

指定 gateway 屬性


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM