需求
多個應(yīng)用系統(tǒng)需要實現(xiàn)登錄功能,并且賬號體系是同一套,同時為了提升使用體驗(一次登錄,即可訪問多個相互信任的應(yīng)用系統(tǒng)),因此需要搭建一套sso系統(tǒng)。sso的基本原理可以參考現(xiàn)實生活中的公園“通票”,一個公園中可能包含多個景區(qū),每個景區(qū)需要分別購票才可游覽,也可以選擇購買通票,有了通票就可以在此多個景區(qū)間無障礙通行
選型
前提是盡量避免重復(fù)造輪子,考慮使用開源方案。開源方案中較為有名的有opensso和cas。前者源于sun公司(oracle),不過目前此開源項目已經(jīng)處于inactive狀態(tài)。后者源于耶魯大學(xué),有成熟的協(xié)議模型
CAS
CAS(Central Authentication Service) 是 Yale 大學(xué)發(fā)起的一個開源項目,從結(jié)構(gòu)體系來看主要包含兩部分:cas server及cas client。前者負(fù)責(zé)完成對用戶的認(rèn)證以及對受限資源的授權(quán)(只能使用https)。后者負(fù)責(zé)保護受限資源以及從server端識別授權(quán)用戶?;窘Y(jié)構(gòu)如下圖:

CAS協(xié)議基于ticket,完整的協(xié)議文檔可以參考http://jasig.github.io/cas/4.2.x/protocol/CAS-Protocol-Specification.html,下面對其核心概念做一簡介
Service Ticket(st)
被用于client端訪問受限資源時身份認(rèn)證的憑據(jù),登錄認(rèn)證成功后由server端生成并回傳給client端
Login Ticket(lt)
在通過用戶名密碼登錄認(rèn)證時作為認(rèn)證憑據(jù)的一部分,在server端展現(xiàn)登錄界面前生成
Ticket-Granting Cookie(tgc)
用于保持sso session的cookie,value是tgt(下面介紹)的key,改cookie為secure cookie
Ticket-Granting Ticket(tgt)
代表包含登錄狀態(tài)的sso session,登錄認(rèn)證成功后由server端生成,后續(xù)的st將基于此派發(fā),tgt 的key作為tgc的value存儲在瀏覽器cookie
其他關(guān)于proxy service的相關(guān)內(nèi)容需要時再做補充
下面來看一下cas流程的時序圖:

配合這張時序圖,整個cas的流程、原理和上面介紹的基本概念應(yīng)該就可以完整的串起來了:
1.在第一次訪問應(yīng)用app1時,由于沒有登錄會直接跳轉(zhuǎn)到Cas Server去進行登錄認(rèn)證,此時將附帶查詢參數(shù)service在Cas Server的登錄地址上,表示登錄成功后將要跳轉(zhuǎn)的地址。此時Cas Server檢查到?jīng)]有之前成功登錄后生成的SSO Session信息,那么就會引導(dǎo)用戶到登錄頁面進行登錄。用戶輸入信息提交登錄請求,Cas Server認(rèn)證成功后將生成對應(yīng)的SSO Session,以及名為CASTGC的cookie,該cookie包含用來確定用戶SSO Session的Ticket Granting Ticket(TGT)。之后會生成一個Service Ticket(ST),并將以ticket作為查詢參數(shù)名,以該ST作為查詢參數(shù)值跳轉(zhuǎn)到登錄時service對應(yīng)的URL。如: http(s)://domain/app1?ticket=ST-2-59fS6KxvmykibRXyoPJE
2.之后的操作對用戶來說都是透明的,即不可見的。app1之后將以service和ticket作為查詢參數(shù)請求Cas Server對service進行驗證,驗證通過后Cas Server將返回當(dāng)前用戶的用戶名等信息。app1就會給當(dāng)前用戶生成其自身的Session,以后該用戶以該Session都可以成功的訪問app1,而不需要再去請求Cas Server進行認(rèn)證。當(dāng)該用戶再去訪問app2的時候,由于其在app2上沒有對應(yīng)的Session信息,將會跳轉(zhuǎn)到Cas Server的登錄地址,Cas Server此時發(fā)現(xiàn)其包含名為CASTGC的cookie,將獲取其中包含的TGT來獲取對應(yīng)的SSO Session,然后會將用戶重定向到app2對應(yīng)的地址,以Service Ticket作為查詢參數(shù)。之后app2會向Cas Server發(fā)送請求校驗該Service Ticket,校驗成功后app2將建立該用戶對應(yīng)的Session信息,以后該用戶以該Session就可以自由的訪問app2了
綜上所述,我們知道,各系統(tǒng)之間的單點登錄是通過Cas Server生成的SSO Session來交流的,而用戶與實際的應(yīng)用系統(tǒng)進行交互的時候,各應(yīng)用系統(tǒng)將建立單獨的Session,以滿足用戶與該系統(tǒng)的交互需求
部分問題及解決方案
1.證書問題,由于使用https,因此需要證書。開發(fā)及測試環(huán)境可自行生成證書(java keytool),需要注意的是證書與域名直接關(guān)聯(lián),因此不可使用ip(否則會在握手階段產(chǎn)生錯誤),另外由于不是CA證書,因此客戶端jvm需要對此證書進行導(dǎo)入(將證書添加到j(luò)vm信任的證書庫)。線上環(huán)境由于是CA證書,因此client端無需進行證書導(dǎo)入
2.出于安全原因,server端會對cookie及webflow標(biāo)識進行加密及簽名,如果沒有設(shè)置密鑰(詳見/WEB-INFO/cas.properties中tgc.encryption.key、tgc.signing.key、webflow.encryption.key、webflow.signing.key),服務(wù)啟動時會產(chǎn)生警告信息并自動生成隨機密鑰(不會報錯),此時需要將此密鑰復(fù)制并保存到/WEB-INFO/cas.propertie相應(yīng)字段,否則多個服務(wù)實例間將由于使用不同的密鑰(各自生成隨機密鑰)導(dǎo)致各種解密失敗,導(dǎo)致cookie及webflow在多實例間不可共享