一圖搞懂Web應用的單點登入

波斯馬發表於2021-12-30

單點登入即Signle Sign On,簡稱SSO。其解決的是使用者在多個站點之間跳轉時需要頻繁登入的問題,比如使用者登入了天貓,就應該無需再使用賬號登入淘寶,它們之間是可以相互信任的,應該自動同步登入狀態。從這點上看單點登入技術的本質是登入狀態在多個站點之間的擴散機制。

先來看下單個程式的登入處理流程,這裡以Web應用程式為例。在單個Web應用程式中使用者通過瀏覽器提交賬號資訊到後端服務,後端服務驗證賬號的有效性,驗證通過後在後端建立一個Session,用來維持使用者的登入狀態,然後向前端返回一個SessionId,前端將這個SessionId儲存起來,這個儲存操作一般是寫入當前域名對應的Cookie,之後每次請求Web頁面的時候都要攜帶這個SessionId,後端服務根據這個SessionId就能識別是哪個使用者,然後就可以進行對應的業務處理。具體登入流程如下圖所示:

Web程式登入流程

那如何在多個站點之間共享登入狀態呢?如果是同一個頂級域名下的不同子域名站點,可以通過共享Cookie的方式,具體操作就是設定Cookie的Domain屬性為同一個頂級域名,則各個站點都能獲取到這個Cookie,也就能獲取到同一個Session,實現登入狀態的共享。不過這種方式的普適性不太好,不同的域名之間就做不到,而且共享Cookie安全性上也會有點問題。

本文將介紹一種更通用的單點登入方式,通過引入一個SSO站點,所有的登入請求和登入狀態同步請求都交給這個站點來處理。這裡假設有兩個站點需要同步登入狀態:站點A 和 站點B,使用者訪問站點A時沒有登入過,需要在SSO站點先登入,然後登入狀態同步到站點A,訪問站B時,因為使用者已經登入過,所以只需要將登入狀態同步到站點B即可。一圖勝千言,下面給出詳細的時序圖,並做一些關鍵步驟說明,具體過程稍微有些複雜,不過仔細閱讀,還是比較容易理解的。

單點登入時序圖

步驟5: 使用者在業務站點未登陸時,統一重定向到SSO站點的登入頁面。這裡有一點需要注意:重定向時需要攜帶使用者訪問A站點的地址,這樣成功登入後才能跳轉回來。

步驟6和步驟27: 重定向到SSO站點時,有兩點需要注意:一是要檢查來源,如果不是允許的業務站點,則應該拒絕請求,這樣比較安全;二是會檢查使用者在SSO站點的登入狀態,如果登入過,瀏覽器會在HTTP請求頭中攜帶SessionId的Cookie,根據這個SessionId可以判斷使用者登入狀態是否有效,如果有效則給業務站點返回一個Ticket,如果無效則返回登入頁面內容,需要使用者先通過賬號登入成功,然後再給業務站點返回Ticket。

步驟15和步驟30: 業務站點收到SSO站點的Ticket之後,還要使用事先分配好的金鑰計算一個簽名,這個金鑰每個站點應該不同,業務站點後臺攜帶這個Ticket和簽名去SSO站點進行驗證。Ticket是SSO站點發放的,自然能夠驗證其有效性;金鑰也是SSO站點發放的,根據簽名的計算規則再算一遍,對比下就知真偽了。然後告知業務站點你可以登入了,併傳送必要的使用者資訊。之所以會有這個步驟,是因為來源的驗證不是那麼可靠,金鑰每家獨一份,安全性就高了很多。

步驟18和步驟33: 業務站點都需要建立自己的使用者Session,然後在瀏覽器寫入對應業務站點的SessionId Cookie。這個Session在服務端可以分別儲存,如果業務規模不大也可以使用同一份儲存,統一儲存時登入狀態可以統一管理。

當前有很多的站點使用JWT做登入認證,這樣有個好處就是分散式環境下不需要集中認證,每個部署節點都擁有完全的認證能力,不過如果需要登出使用者的時候,就很難實現同步登出。有一些解決方案,比如認證Token的生存期短一點,再增加一個重新整理Token,重新整理Token時訪問集中的認證服務;或者使用一個高效的黑名單機制,每次都檢查黑名單等。如果業務規模不是很大,都不如統一Session的機制簡單,比如使用Redis儲存Session資訊,輕鬆處理千級萬級併發。

以上就是本文的全部內容了,重點就是那張單點登入的時序圖,想不明白的時候可以多擼幾遍,如有錯漏歡迎指正。

關注公眾號:螢火架構

收穫更多架構知識,請關注公眾號 螢火架構。原創內容,轉載請註明出處。

相關文章