對於單點登入,你不得不瞭解的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楊洋的網際網路打工人