對於單點登錄,你不得不瞭解的CAS

語言: CN / TW / HK

開啟掘金成長之旅!這是我參與「掘金日新計劃 · 2 月更文挑戰」的第 1 天,點擊查看活動詳情

大家好,我是車轍。之前我們通過面試的形式,講了JWT實現單點登錄(SSO)的設計思路,並且到最後也留下了疑問,什麼是CAS

沒看過的同學建議點擊下方鏈接先看下,兩者還是有一定連貫性的。

傳送門:面試系列:4000字長文,讓你瞭解單點登錄(一)

寒暄開始

今天是上班的第一天,剛進公司就見到了上次的面試官,穿着格子襯衫和拖鞋,我們就叫他老餘吧。老餘看見我就開始勾肩搭背聊起來了,完全就是自來熟的樣子,和我最近看的少年歌行裏的某人很像。

什麼是CAS呢

老餘:上次你説到了CAS,你覺得CAS是什麼?

我:之前我們面試的時候,我講了JWT單點登錄帶來的問題,然後慢慢優化,最後衍變成了中心化單點登錄系統,也就是CAS的方案。

CAS(Central Authentication Service),中心認證服務,就是單點登錄的某種實現方案。你可以把它理解為它是一個登錄中轉站,通過SSO站點,既解決了Cookie跨域的問題,同時還通過SSO服務端實現了登錄驗證的中心化。

這裏的SSO指的是:SSO系統

它的設計流程是怎樣的

老餘:你能不能講下它的大致實現思路,這説的也太虛頭巴腦了,簡直是聽君一席話,如聽一席話。
我:你別急呀,先看下它的官方流程圖。 image.png

重定向到SSO

首先,用户想要訪問系統A的頁面1,自然會調用www.chezhe1.com的限制接口,(比如説用户信息等接口登錄後才能訪問)。

接下來 系統A 服務端一般會在攔截器【也可以是過濾器,AOP 啥的】中根據Cookie中的SessionId判斷用户是否已登錄。如果未登錄,則重定向到SSO系統的登錄頁面,並且帶上自己的回調地址,便於用户在SSO系統登錄成功後返回。此時回調地址是:www.sso.com?url=www.chezhe1.com

這個回調地址大家應該都不會陌生吧,像那種異步接口或者微信授權、支付都會涉及到這塊內容。不是很瞭解的下面會解釋~
另外這個回調地址還必須是前端頁面地址,主要用於回調後和當前系統建立會話。

此時如下圖所示: image.png

用户登錄

  1. 在重定向到SSO登錄頁後,需要在頁面加載時調用接口,根據SessionId判斷當前用户在SSO系統下是否已登錄。【注意這時候已經在 SSO 系統的域名下了,也就意味着此時Cookie中的domain已經變成了sso.com

    為什麼又要判斷是否登錄?因為在 CAS 這個方案中,只有在SSO系統中為登錄狀態才能表明用户已登錄。

  2. 如果未登錄,展現賬號密碼框,讓用户輸入後進行SSO系統的登錄。登錄成功後,SSO頁面和SSO服務端建立起了會話。 此時流程圖如下所示:

image.png

安全驗證

老餘:你這裏有一個很大的漏洞你發現沒有?
我:emm,我當然知道。

對於中心化系統,我們一般會分發對應的AppId,然後要求每個應用設置白名單域名。所以在這裏我們還得驗證AppId的有效性,白名單域名和回調地址域名是否匹配。否則有些人在回調地址上寫個黃色網站那不是涼涼。

image.png

獲取用户信息登錄

  1. 在正常的系統中用户登錄後,一般需要跳轉到業務界面。但是在SSO系統登錄後,需要跳轉到原先的系統A,這個系統A地址怎麼來?還記得重定向到SSO頁面時帶的回調地址嗎?

image.png

通過這個回調地址,我們就能很輕易的在用户登錄成功後,返回到原先的業務系統。

  1. 於是用户登錄成功後根據回調地址,帶上ticket,重定向回系統A,重定向地址為:www.chezhe1.com?ticket=123456a
  2. 接着根據ticket,從SSO服務端中獲取Token。在此過程中,需要對ticket進行驗證。
  3. 根據tokenSSO服務端中獲取用户信息。在此過程中,需要對token進行驗證。
  4. 獲取用户信息後進行登錄,至此係統A頁面和系統A服務端建立起了會話,登錄成功。

此時流程圖如下所示:

image.png

別以為這麼快就結束了哦,我這邊提出幾個問題,只有把這些想明白了,才算是真的清楚了。 - 為什麼需要 Ticket? - 驗證 Ticket 需要驗證哪些內容? - 為什麼需要 Token? - 驗證 Token 需要驗證哪些內容? - 如果沒有Token,我直接通過Ticket 獲取用户信息是否可行?

為什麼需要 Ticket

我們可以反着想,如果沒有Ticket,我們該用哪種方式獲取Token或者説用户信息?你又該怎麼證明你已經登錄成功?用Cookie嗎,明顯是不行的。

所以説,Ticket是一個憑證,是當前用户登錄成功後的產物。沒了它,你證明不了你自己。

驗證 Ticket 需要驗證哪些內容

  1. 簽名:對於這種中心化系統,為了安全,絕大數接口請求都會有着驗籤機制,也就是驗證這個數據是否被篡改。至於驗籤的具體實現,五花八門都有。
  2. 真實性:驗籤成功後拿到Ticket,需要驗證Ticket是否是真實存在的,不能説隨便造一個我就給你返回Token吧。
  3. 使用次數:為了安全性,Ticket只能使用一次,否則就報錯,因為Ticket很多情況下是拼接在URL上的,肉眼可見。
  4. 有效期:另外則是Ticket的時效,超過一定時間內,這個Ticket會過期。比如微信授權的Code只有5分鐘的有效期。
  5. ......

為什麼需要 Token?

只有通過Token我們才能從SSO系統中獲取用户信息,但是為什麼需要Token呢?我直接通過Ticket獲取用户信息不行嗎?

答案當然是不行的,首先為了保證安全性Ticket只能使用一次,另外Ticket具有時效性。但這與某些系統的業務存在一定衝突。因此通過使用Token增加有效時間,同時保證重複使用。

驗證 Token 需要驗證哪些內容?

和驗證 Ticket類似 1. 簽名 2. 真實性 3. 有效期

如果沒有 Token,我直接通過 Ticket 獲取用户信息是否可行?

這個內容其實上面已經給出答案了,從實現上是可行的,從設計上不應該,因為TicketToken的職責不一樣,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服務端建立了會話,並且因為CookieSSO這個域名下是共享的,所以此時SSO系統會判斷當前用户已登錄。然後就是之前的那一套邏輯了。 此時流程圖如下所示:

image.png

技術以外的事

老餘:不錯不錯,理解的還可以。你發現這套系統裏,做的最多的是什麼,有什麼技術之外的感悟沒。説到這,老餘歎了口氣。

我:我懂,做的最多的就是驗證了,驗證真實性、有效性、白名單這些。明明一件很簡單的事,最後搞的那麼複雜。像現在銀行裏取錢一樣,各種條條框框的限制。我有時候會在想,技術發展、思想變革對於人類文明毋庸置疑是有益的,但是對於我們人類真的是一件好事嗎?如果我們人類全是機器人那樣的思維是不是會更好點?

image.png

老餘:我就隨便一提,你咋巴拉巴拉了這麼多。我只清楚一點,擁有七情六慾的人總是好過沒有情感的機器人的。好了,幹活去吧。

總結

這一篇內容就到這了,我們聊了下關於單點登錄的 CAS 設計思路,其實CAS 往大了講還能講很多,可惜我的技術儲備還不夠,以後有機會補充。如果想理解的更深刻,也可以去看下微信授權流程,應該會有幫助。

最後還順便提了點技術之外的事,記得有句話叫做:科學的盡頭是哲學,我好像開始慢慢理解這句話的意思了。

如果這篇文章對您有所幫助,可以關注我的公眾號《車轍的編程學習圈》,也可以在我的博客網站掃碼關注我的博客網站

我是車轍,掘金小冊《SkyWalking》作者,一名常被HR調侃為XX楊洋的互聯網打工人