對於單點登錄,你不得不瞭解的CAS
開啟掘金成長之旅!這是我參與「掘金日新計劃 · 2 月更文挑戰」的第 1 天,點擊查看活動詳情
大家好,我是車轍。之前我們通過面試的形式,講了JWT
實現單點登錄(SSO)的設計思路,並且到最後也留下了疑問,什麼是CAS
。
沒看過的同學建議點擊下方鏈接先看下,兩者還是有一定連貫性的。
寒暄開始
今天是上班的第一天,剛進公司就見到了上次的面試官,穿着格子襯衫和拖鞋,我們就叫他老餘吧。老餘看見我就開始勾肩搭背聊起來了,完全就是自來熟的樣子,和我最近看的少年歌行裏的某人很像。
什麼是CAS呢
老餘:上次你説到了CAS
,你覺得CAS
是什麼?
我:之前我們面試的時候,我講了JWT
單點登錄帶來的問題,然後慢慢優化,最後衍變成了中心化單點登錄系統,也就是CAS
的方案。
CAS(Central Authentication Service),中心認證服務,就是單點登錄的某種實現方案。你可以把它理解為它是一個登錄中轉站,通過SSO
站點,既解決了Cookie
跨域的問題,同時還通過SSO
服務端實現了登錄驗證的中心化。
這裏的SSO指的是:SSO系統
它的設計流程是怎樣的
老餘:你能不能講下它的大致實現思路,這説的也太虛頭巴腦了,簡直是聽君一席話,如聽一席話。
我:你別急呀,先看下它的官方流程圖。
重定向到SSO
首先,用户想要訪問系統A的頁面1,自然會調用www.chezhe1.com
的限制接口,(比如説用户信息等接口登錄後才能訪問)。
接下來 系統A 服務端一般會在攔截器【也可以是過濾器,AOP 啥的】中根據Cookie
中的SessionId
判斷用户是否已登錄。如果未登錄,則重定向到SSO
系統的登錄頁面,並且帶上自己的回調地址,便於用户在SSO
系統登錄成功後返回。此時回調地址是:www.sso.com?url=www.chezhe1.com
。
這個回調地址大家應該都不會陌生吧,像那種異步接口或者微信授權、支付都會涉及到這塊內容。不是很瞭解的下面會解釋~
另外這個回調地址還必須是前端頁面地址,主要用於回調後和當前系統建立會話。
此時如下圖所示:
用户登錄
-
在重定向到
SSO
登錄頁後,需要在頁面加載時調用接口,根據SessionId
判斷當前用户在SSO
系統下是否已登錄。【注意這時候已經在 SSO 系統的域名下了,也就意味着此時Cookie
中的domain
已經變成了sso.com
】為什麼又要判斷是否登錄?因為在 CAS 這個方案中,只有在SSO系統中為登錄狀態才能表明用户已登錄。
-
如果未登錄,展現賬號密碼框,讓用户輸入後進行
SSO
系統的登錄。登錄成功後,SSO
頁面和SSO
服務端建立起了會話。 此時流程圖如下所示:
安全驗證
老餘:你這裏有一個很大的漏洞你發現沒有?
我:emm,我當然知道。
對於中心化系統,我們一般會分發對應的AppId
,然後要求每個應用設置白名單域名。所以在這裏我們還得驗證AppId
的有效性,白名單域名和回調地址域名是否匹配。否則有些人在回調地址上寫個黃色網站那不是涼涼。
獲取用户信息登錄
- 在正常的系統中用户登錄後,一般需要跳轉到業務界面。但是在
SSO
系統登錄後,需要跳轉到原先的系統A,這個系統A地址怎麼來?還記得重定向到SSO
頁面時帶的回調地址嗎?
通過這個回調地址,我們就能很輕易的在用户登錄成功後,返回到原先的業務系統。
- 於是用户登錄成功後根據回調地址,帶上
ticket
,重定向回系統A,重定向地址為:www.chezhe1.com?ticket=123456a
。 - 接着根據
ticket
,從SSO
服務端中獲取Token
。在此過程中,需要對ticket
進行驗證。 - 根據
token
從SSO
服務端中獲取用户信息。在此過程中,需要對token
進行驗證。 - 獲取用户信息後進行登錄,至此係統A頁面和系統A服務端建立起了會話,登錄成功。
此時流程圖如下所示:
別以為這麼快就結束了哦,我這邊提出幾個問題,只有把這些想明白了,才算是真的清楚了。 - 為什麼需要 Ticket? - 驗證 Ticket 需要驗證哪些內容? - 為什麼需要 Token? - 驗證 Token 需要驗證哪些內容? - 如果沒有Token,我直接通過Ticket 獲取用户信息是否可行?
為什麼需要 Ticket
我們可以反着想,如果沒有Ticket
,我們該用哪種方式獲取Token
或者説用户信息?你又該怎麼證明你已經登錄成功?用Cookie
嗎,明顯是不行的。
所以説,Ticket
是一個憑證,是當前用户登錄成功後的產物。沒了它,你證明不了你自己。
驗證 Ticket 需要驗證哪些內容
- 簽名:對於這種中心化系統,為了安全,絕大數接口請求都會有着驗籤機制,也就是驗證這個數據是否被篡改。至於驗籤的具體實現,五花八門都有。
- 真實性:驗籤成功後拿到
Ticket
,需要驗證Ticket
是否是真實存在的,不能説隨便造一個我就給你返回Token
吧。 - 使用次數:為了安全性,
Ticket
只能使用一次,否則就報錯,因為Ticket
很多情況下是拼接在URL
上的,肉眼可見。 - 有效期:另外則是
Ticket
的時效,超過一定時間內,這個Ticket
會過期。比如微信授權的Code
只有5分鐘的有效期。 - ......
為什麼需要 Token?
只有通過Token
我們才能從SSO
系統中獲取用户信息,但是為什麼需要Token
呢?我直接通過Ticket
獲取用户信息不行嗎?
答案當然是不行的,首先為了保證安全性,Ticket
只能使用一次,另外Ticket
具有時效性。但這與某些系統的業務存在一定衝突。因此通過使用Token
增加有效時間,同時保證重複使用。
驗證 Token 需要驗證哪些內容?
和驗證 Ticket類似 1. 簽名 2. 真實性 3. 有效期
如果沒有 Token,我直接通過 Ticket 獲取用户信息是否可行?
這個內容其實上面已經給出答案了,從實現上是可行的,從設計上不應該,因為Ticket
和Token
的職責不一樣,Ticket
是登錄成功的票據,Token
是獲取用户信息的票據。
用户登錄系統B流程
老餘:系統A登錄成功後,那系統B的流程呢?
我:那就更簡單了。
比如説此時用户想要訪問系統B,www.chezhe2.com
的限制接口,系統B服務端一般會在攔截器【也可以是過濾器,AOP 啥的】中根據Cookie
中的SessionId
判斷用户是否已登錄。此時在系統B中該系統肯定未登錄,於是重定向到SSO
系統的登錄頁面,並且帶上自己的回調地址,便於用户在SSO
系統登錄成功後返回。回調地址是:www.sso.com?url=www.chezhe2.com。
我們知道之前SSO頁面已經與SSO服務端建立了會話,並且因為Cookie
在SSO
這個域名下是共享的,所以此時SSO
系統會判斷當前用户已登錄。然後就是之前的那一套邏輯了。
此時流程圖如下所示:
技術以外的事
老餘:不錯不錯,理解的還可以。你發現這套系統裏,做的最多的是什麼,有什麼技術之外的感悟沒。説到這,老餘歎了口氣。
我:我懂,做的最多的就是驗證了,驗證真實性、有效性、白名單這些。明明一件很簡單的事,最後搞的那麼複雜。像現在銀行裏取錢一樣,各種條條框框的限制。我有時候會在想,技術發展、思想變革對於人類文明毋庸置疑是有益的,但是對於我們人類真的是一件好事嗎?如果我們人類全是機器人那樣的思維是不是會更好點?
老餘:我就隨便一提,你咋巴拉巴拉了這麼多。我只清楚一點,擁有七情六慾的人總是好過沒有情感的機器人的。好了,幹活去吧。
總結
這一篇內容就到這了,我們聊了下關於單點登錄的 CAS 設計思路,其實CAS 往大了講還能講很多,可惜我的技術儲備還不夠,以後有機會補充。如果想理解的更深刻,也可以去看下微信授權流程,應該會有幫助。
最後還順便提了點技術之外的事,記得有句話叫做:科學的盡頭是哲學,我好像開始慢慢理解這句話的意思了。
如果這篇文章對您有所幫助,可以關注我的公眾號《車轍的編程學習圈》,也可以在我的博客網站掃碼關注我的博客網站。
我是車轍,掘金小冊《SkyWalking》作者,一名常被HR調侃為XX楊洋的互聯網打工人