CAS
這篇需要搭配SSO 技術實踐: CAS整合JWT(Server篇)一起看,這篇主要會介紹關於jwt如何在client這邊驗證,以及處理關於server發過來的SLO request怎麼處理。
另外,關於此篇不管是實作還是設定,都只是基於開發練習用,實際上關於認證及驗證的方式相信會有更好的方式,此篇僅為了練習而採用簡單的方式實作。
Server使用套件(請加入在build.gradle):
Client使用套件(請加入在pom.xml):
因為整體web.xml配置有點長,會拆局部一一說明。
可參考: java cas 單點登入web.xml配置[1]
由於filter的順序是會影響實際先流入哪個filter,因此順序非常重要,SSO Filter之所以需要擺第一個,是因為這是主要在控管sso狀態的filter。
下方的listener則是負責監聽slo request的部分,這個listener如果沒有的話,client會收不到訊息,而server則是不管發出的slo request是否有成功,都不會報異常!! 所以想知道問題出在哪,就必須把中斷點下在filter內,當初也是因為這樣才發現slo request溝通過程ssl handshake失敗…
此filter負責導向CAS Server做登入認證,如果是剛從git抓下來解壓後,他應該是會寫成/*
的pattern,但因為我們要讓只有經過登入頁面的request才導去cas server,因此url pattern需要設定成client登入的路徑。
此filter是用來驗證ticket的部分,但請注意!! 原本如果只是單純的CAS流程,這邊的確是需要設定的,但因為今天我們採取的是搭配jwt的流程,變成驗證的動作是在client端執行,所以這整段都需要註解掉,不需要設定,也就是說下面這段看看就好~
這個filter底層實現了能透過sso中已登錄的session取得principleUser的資料,如果是透過CAS Server驗證成功的話,會塞principle資料到session中,但因為我們沒透過CAS Server做驗證,所以基本上想取得資料,都是透過parse jwt string,如果直接使用session.getRemoteUser()會得到null。
主要負責request流進來後的走向,這屬於自己實作的部分,不用完全參照,只要登入流程可以work即可,這邊設定為不管任何入口都會攔住進行檢查是否登入。
檢查是否直接攜帶ticket,有的話直接導入到jwtValidate。
這邊有做接收及處理server發送過來的slo request,saml字串處理的部分有另一部分實作。
這邊主要是當作一開始進來的入口,如果是直接走到login或logout的入口,直接往下流即可,因為下面會有CAS Authentication Filter
接住後導向CAS Server進行登入。
如果是request其他路徑,就檢查有沒有帶jwt屬性而且驗證過沒有,都沒有的話就導去登入入口,有jwt就導去驗證~
這邊單純將login近來的入口導到index.jsp裡面。
由於jwt字串驗證是在client端實作,這邊先提供cas社群的參考資料: jwt-validation[2]
關於jwt、jws、jwe三者之間的關係,這篇文章非常有幫助: JWT & JWE & JWS 大亂鬥![3]
因為在CAS Server jwt有配置encryption key的關係,因此正確來說這邊不單純只是用到jws,而是應該稱jwe才對。
由於signing key只是用來驗證簽名的部分,如果想為內容增加安全性,可以使用encryption key把jwt當中的payload再加密一次,成為jwe之後丟給client處理,所以在client也需要配兩把key,但對於jwt的設定來說,encryption key為非必要,只需要設置signing key即可。
為了讓client端知道使用者的登入情形,所以我有寫了一個UserList去裝當登入成功後的使用者sessio、id、Service Ticket等等資料,這樣當CAS Server發slo request帶來的Service Ticket時,才能找到要廢除哪個session,但這邊只是為了實驗方便,其實應該是要搭配資料庫之類的才會比較符合實際使用情形。
要注意的是由於RFC規定的關係,傳輸的字串都會經過Base64 URLEncode的關係,一開始我完全不知道這件事,導致有時jwt拿去verifySignature()就會fail,找了很久後來才發現把%3D之類的換回=就成功了…
關於這部分的處理可參考: Java 程式處理網址 URL 百分比編碼與解碼教學[4]
這一份其實參考價值不大,可自由實作或者透過資料庫拿資料都能達成,但為了閱讀完整性還是放上連結。
UserList.java
由index.jsp連結到client logout的部分,是透過get的方式,同時也順便直接廢掉session,但是CAS Server打過來是透過POST的方式,帶了SAML格式的字串過來,因此post的部分要另外處理。
這邊就是單純直接把saml字串拆出來之後用第三方套件處理,要注意的是他傳過來的tag有的是saml開頭,有些是samlp的部分,檔案連結在下方。
SamlUtils.java
[1] java cas 單點登入web.xml配置
[2] jwt-validation
[3] JWT & JWE & JWS 大亂鬥!
[4] Java 程式處理網址 URL 百分比編碼與解碼教學