當前位置: 妍妍網 > 碼農

單點登入(SSO)實作詳解!!!

2024-03-04碼農



單點登入是什麽?你是怎麽理解的?單點登入是如何實作的

普通登入

提到單點登入,首先可以想到傳統登入,透過登入頁面根據使用者名稱查詢使用者資訊,判斷密碼是否正確,正確則將使用者資訊寫到session,存取的時候透過從session中獲取使用者資訊,判斷是否已登入,登入則允許存取。

普通登入的缺點

由於session不能共享,服務越來越多,並且還服務還搭建集群,導致每存取另外一個服務都需要重新登入。

單點登入

單點登入有個簡稱是sso,它是一個功能可以控制多個有聯系的系統操作,簡單地理解為透過單點登入可以讓使用者只需要登入一次軟體或者系統,那麽同系統下的平台都可以免去再次註冊、驗證、存取許可權的麻煩程式,通俗易懂的理解為一次性登入也可以一次性下線。

前端需要知道的單點登入概述:

1、一個系統登入流程:使用者進入系統——未登入——跳轉登入界面——使用者名稱和密碼發送——伺服器端驗證後,設定一個cookie發送到瀏覽器,設定一個session存放在伺服器——使用者再次請求(帶上cookie)——伺服器驗證cookie和session匹配後,就可以進行業務了。

2、多個系統登入:如果一個大公司有很多系統,a.seafile.com, b.seafile.com,c.seafile.com。這些系統都需要登入,如果使用者在不同系統間登入需要多次輸入密碼,使用者體驗很不好。所以使用 SSO (single sign on) 單點登入實作。

3、相同網域名稱,不同子網域名稱下的單點登入:在瀏覽器端,根據同源策略,不同子網域名稱的cookie不能共享。所以設定SSO的網域名稱為根網域名稱。SSO登入驗證後,子網域名稱可以存取根網域名稱的 cookie,即可完成校驗。在伺服器端,可以設定多個子網域名稱session共享(Spring-session)

4、不同網域名稱下的單點登入:CAS流程:使用者登入子系統時未登入,跳轉到 SSO 登入界面,成功登入後,SSO 生成一個 ST (service ticket )。使用者登入不同的網域名稱時,都會跳轉到 SSO,然後 SSO 帶著 ST 返回到不同的子網域名稱,子網域名稱中發出請求驗證 ST 的正確性(防止篡改請求)。驗證透過後即可完成不同的業務。

單點登入需求

在計畫初期,公司中使用的系統很少,通常一個或者兩個,每個系統都有自己的登入系統,使用者用自己的帳號登入,很方便。

但隨著公司的不斷發展,用到的系統隨之增多,使用者在操作不同的系統時,需要多次登入,而且每個系統的帳號都不一樣,這對於使用者來說,是很不好的體驗。於是,就想到是不是可以在一個系統登入,其他系統就不用登入了呢?這就是單點登入要解決的問題。

單點登入英文全稱Single Sign On,簡稱就是SSO。它的解釋是:在多個套用系統中,只需要登入一次,就可以存取其他相互信任的套用系統。

單點登入(Single Sign On),簡稱為 SSO,是比較流行的企業業務整合的解決方案之一。SSO的定義是在多個套用系統中,使用者只需要登入一次就可以存取所有相互信任的套用系統。

如圖所示,圖中有4個系統,分別是Application1、Application2、Application3、和SSO。Application1、Application2、Application3沒有登入模組,而SSO只有登入模組,沒有其他的業務模組,當Application1、Application2、Application3需要登入時,將跳到SSO系統,SSO系統完成登入,其他的套用系統也就隨之登入了。這完全符合我們對單點登入(SSO)的定義。

SSO 機制實作流程

使用者首次存取時,需要在認證中心登入:

  1. 使用者存取網站 a.com 下的 pageA 頁面。

  2. 由於沒有登入,則會重新導向到認證中心,並帶上回呼地址 (http://www.sso.com?return_uri=a.com/pageA,以便登录后直接进入对应页面。 )

  3. 使用者在認證中心輸入帳號密碼,送出登入。

  4. 認證中心驗證帳號密碼有效,然後重新導向 a.com?ticket=123 帶上授權碼 ticket,並將認證中心 sso.com 的登入態寫入 Cookie。

  5. 在 a.com 伺服器中,拿著 ticket 向認證中心確認,授權碼 ticket 真實有效。

  6. 驗證成功後,伺服器將登入資訊寫入 Cookie(此時客戶端有 2 個 Cookie 分別存有 a.com 和 sso.com 的登入台)。

認證中心登入完成之後,繼續存取 a.com 下的其他頁面:

這個時候,由於 a.com 存在已登入的 Cookie 資訊,所以伺服器端直接認證成功。

如果認證中心登入完成之後,存取 b.com 下的頁面:

這個時候,由於認證中心存在之前登入過的 Cookie ,所以也不用再次輸入帳號密碼,直接返回第 4 步,下發 ticket b.com 即可。

SSO 機制實作方式

單點登入主要有三種實作方式:

  1. 父域 Cookie

  2. 認證中心

  3. LocalStorage 跨域

一般情況下,使用者的登入狀態是記錄在 Session 中的,要實作共享登入狀態,就要先共享 Session,但是由於不同的套用系統有著不同的網域名稱,盡管 Session 共享了,但是由於 SessionId 是往往保存在瀏覽器 Cookie 中的,因此存在作用域的限制,無法跨網域名稱傳遞,也就是說當使用者在 a.com 中登入後,Session Id 僅在瀏覽器存取 a.com 時才會自動在請求頭中攜帶,而當瀏覽器存取 b.com 時,Session Id 是不會被帶過去的。實作單點登入的關鍵在於,如何讓 Session Id(或 Token)在多個域中共享。

1. 父域 Cookie

Cookie 的作用域由 domain 內容和 path 內容共同決定。domain 內容的有效值為當前域或其父域的網域名稱/IP地址,在 Tomcat 中,domain 內容預設為當前域的網域名稱/IP地址。path 內容的有效值是以「/」開頭的路徑,在 Tomcat 中,path 內容預設為當前 Web 套用的上下文路徑。

如果將 Cookie 的 domain 內容設定為當前域的父域,那麽就認為它是父域 Cookie。Cookie 有一個特點,即父域中的 Cookie 被子體所共享,也就是說,子體會自動繼承父域中的 Cookie。

利用 Cookie 的這個特點,可以將 Session Id(或 Token)保存到父域中就可以了。我們只需要將 Cookie 的 domain 內容設定為父域的網域名稱(主網域名稱),同時將 Cookie 的 path 內容設定為根路徑,這樣所有的子體套用就都可以存取到這個 Cookie 了。不過這要求套用系統的網域名稱需建立在一個共同的主網域名稱之下,如 tieba.baidu.com 和 map.baidu.com,它們都建立在 baidu.com 這個主網域名稱之下,那麽它們就可以透過這種方式來實作單點登入。

總結:此種實作方式比較簡單,但不支持跨主網域名稱。

2. 認證中心

我們可以部署一個認證中心,認證中心就是一個專門負責處理登入請求的獨立的 Web 服務。

使用者統一在認證中心進行登入,登入成功後,認證中心記錄使用者的登入狀態,並將 Token 寫入 Cookie。(註意這個 Cookie 是認證中心的,套用系統是存取不到的)

套用系統檢查當前請求有沒有 Token,如果沒有,說明使用者在當前系統中尚未登入,那麽就將頁面跳轉至認證中心進行登入。由於這個操作會將認證中心的 Cookie 自動帶過去,因此,認證中心能夠根據 Cookie 知道使用者是否已經登入過了。如果認證中心發現使用者尚未登入,則返回登入頁面,等待使用者登入,如果發現使用者已經登入過了,就不會讓使用者再次登入了,而是會跳轉回目標 URL ,並在跳轉前生成一個 Token,拼接在目標 URL 的後面,回傳給目標套用系統。

套用系統拿到 Token 之後,還需要向認證中心確認下 Token 的合法性,防止使用者偽造。確認無誤後,套用系統記錄使用者的登入狀態,並將 Token 寫入 Cookie,然後給本次存取放行。(這個 Cookie 是當前套用系統的,其他套用系統是存取不到的)當使用者再次存取當前套用系統時,就會自動帶上這個 Token,套用系統驗證 Token 發現使用者已登入,於是就不會有認證中心什麽事了。

總結:此種實作方式相對復雜,支持跨域,擴充套件性好,是單點登入的標準做法。

3. LocalStorage 跨域

單點登入的關鍵在於,如何讓 Session Id(或 Token)在多個域中共享。但是 Cookie 是不支持跨主網域名稱的,而且瀏覽器對 Cookie 的跨域限制越來越嚴格。

在前後端分離的情況下,完全可以不使用 Cookie,我們可以選擇將 Session Id (或 Token )保存到瀏覽器的 LocalStorage 中,讓前端在每次向後端發送請求時,主動將 LocalStorage 的數據傳遞給伺服端。這些都是由前端來控制的,後端需要做的僅僅是在使用者登入成功後,將 Session Id (或 Token )放在響應體中傳遞給前端。

在這樣的場景下,單點登入完全可以在前端實作。前端拿到 Session Id (或 Token )後,除了將它寫入自己的 LocalStorage 中之外,還可以透過特殊手段將它寫入多個其他域下的 LocalStorage 中。

總結:此種實作方式完全由前端控制,幾乎不需要後端參與,同樣支持跨域

SSO 單點登入結束

目前我們已經完成了單點登入,在同一套認證中心的管理下,多個產品可以共享登入態。現在我們需要考慮結束了,即:在一個產品中結束了登入,怎麽讓其他的產品也都結束登入?

原理其實不難,可以在每一個產品在向認證中心驗證 ticket(token) 時,其實可以順帶將自己的結束登入 api 發送到認證中心。

當某個產品 c.com 結束登入時:

清空 c.com 中的登入態 Cookie。請求認證中心 sso.com 中的結束 api。認證中心遍歷下發過 ticket(token) 的所有產品,並呼叫對應的結束 api,完成結束。

作者:愛吃橘子的程式猿  https://juejin.cn/post/7282692430117748755