
一、是什么
單點(diǎn)登錄(Single Sign On),簡稱為 SSO,是目前比較流行的企業(yè)業(yè)務(wù)整合的解決方案之一
SSO的定義是在多個應(yīng)用系統(tǒng)中,用戶只需要登錄一次就可以訪問所有相互信任的應(yīng)用系統(tǒng)
SSO 一般都需要一個獨(dú)立的認(rèn)證中心(passport),子系統(tǒng)的登錄均得通過passport
,子系統(tǒng)本身將不參與登錄操作
當(dāng)一個系統(tǒng)成功登錄以后,passport
將會頒發(fā)一個令牌給各個子系統(tǒng),子系統(tǒng)可以拿著令牌會獲取各自的受保護(hù)資源,為了減少頻繁認(rèn)證,各個子系統(tǒng)在被passport
授權(quán)以后,會建立一個局部會話,在一定時間內(nèi)可以無需再次向passport
發(fā)起認(rèn)證

上圖有四個系統(tǒng),分別是Application1
、Application2
、Application3
、和SSO
,當(dāng)Application1
、Application2
、Application3
需要登錄時,將跳到SSO
系統(tǒng),SSO
系統(tǒng)完成登錄,其他的應(yīng)用系統(tǒng)也就隨之登錄了
舉個例子
淘寶、天貓都屬于阿里旗下,當(dāng)用戶登錄淘寶后,再打開天貓,系統(tǒng)便自動幫用戶登錄了天貓,這種現(xiàn)象就屬于單點(diǎn)登錄
二、如何實(shí)現(xiàn)
同域名下的單點(diǎn)登錄
cookie
的domain
屬性設(shè)置為當(dāng)前域的父域,并且父域的cookie
會被子域所共享。path
屬性默認(rèn)為web
應(yīng)用的上下文路徑
利用 Cookie
的這個特點(diǎn),沒錯,我們只需要將Cookie
的domain
屬性設(shè)置為父域的域名(主域名),同時將 Cookie
的path
屬性設(shè)置為根路徑,將 Session ID
(或 Token
)保存到父域中。這樣所有的子域應(yīng)用就都可以訪問到這個Cookie
不過這要求應(yīng)用系統(tǒng)的域名需建立在一個共同的主域名之下,如 tieba.baidu.com
和 map.baidu.com
,它們都建立在 baidu.com
這個主域名之下,那么它們就可以通過這種方式來實(shí)現(xiàn)單點(diǎn)登錄
不同域名下的單點(diǎn)登錄(一)
如果是不同域的情況下,Cookie
是不共享的,這里我們可以部署一個認(rèn)證中心,用于專門處理登錄請求的獨(dú)立的 Web
服務(wù)
用戶統(tǒng)一在認(rèn)證中心進(jìn)行登錄,登錄成功后,認(rèn)證中心記錄用戶的登錄狀態(tài),并將 token
寫入 Cookie
(注意這個 Cookie
是認(rèn)證中心的,應(yīng)用系統(tǒng)是訪問不到的)
應(yīng)用系統(tǒng)檢查當(dāng)前請求有沒有 Token
,如果沒有,說明用戶在當(dāng)前系統(tǒng)中尚未登錄,那么就將頁面跳轉(zhuǎn)至認(rèn)證中心
由于這個操作會將認(rèn)證中心的 Cookie
自動帶過去,因此,認(rèn)證中心能夠根據(jù) Cookie
知道用戶是否已經(jīng)登錄過了
如果認(rèn)證中心發(fā)現(xiàn)用戶尚未登錄,則返回登錄頁面,等待用戶登錄
如果發(fā)現(xiàn)用戶已經(jīng)登錄過了,就不會讓用戶再次登錄了,而是會跳轉(zhuǎn)回目標(biāo) URL
,并在跳轉(zhuǎn)前生成一個 Token
,拼接在目標(biāo)URL
的后面,回傳給目標(biāo)應(yīng)用系統(tǒng)
應(yīng)用系統(tǒng)拿到 Token
之后,還需要向認(rèn)證中心確認(rèn)下 Token
的合法性,防止用戶偽造。確認(rèn)無誤后,應(yīng)用系統(tǒng)記錄用戶的登錄狀態(tài),并將 Token
寫入Cookie
,然后給本次訪問放行。(注意這個 Cookie
是當(dāng)前應(yīng)用系統(tǒng)的)當(dāng)用戶再次訪問當(dāng)前應(yīng)用系統(tǒng)時,就會自動帶上這個 Token
,應(yīng)用系統(tǒng)驗(yàn)證 Token 發(fā)現(xiàn)用戶已登錄,于是就不會有認(rèn)證中心什么事了
此種實(shí)現(xiàn)方式相對復(fù)雜,支持跨域,擴(kuò)展性好,是單點(diǎn)登錄的標(biāo)準(zhǔn)做法
不同域名下的單點(diǎn)登錄(二)
可以選擇將 Session ID
(或 Token
)保存到瀏覽器的 LocalStorage
中,讓前端在每次向后端發(fā)送請求時,主動將LocalStorage
的數(shù)據(jù)傳遞給服務(wù)端
這些都是由前端來控制的,后端需要做的僅僅是在用戶登錄成功后,將 Session ID
(或 Token
)放在響應(yīng)體中傳遞給前端
單點(diǎn)登錄完全可以在前端實(shí)現(xiàn)。前端拿到 Session ID
(或 Token
)后,除了將它寫入自己的 LocalStorage
中之外,還可以通過特殊手段將它寫入多個其他域下的 LocalStorage
中
關(guān)鍵代碼如下:
// 獲取 token
var token = result.data.token;
// 動態(tài)創(chuàng)建一個不可見的iframe,在iframe中加載一個跨域HTML
var iframe = document.createElement("iframe");
iframe.src = "http://app1.com/localstorage.html";
document.body.append(iframe);
// 使用postMessage()方法將token傳遞給iframe
setTimeout(function () {
iframe.contentWindow.postMessage(token, "http://app1.com");
}, 4000);
setTimeout(function () {
iframe.remove();
}, 6000);
// 在這個iframe所加載的HTML中綁定一個事件監(jiān)聽器,當(dāng)事件被觸發(fā)時,把接收到的token數(shù)據(jù)寫入localStorage
window.addEventListener('message', function (event) {
localStorage.setItem('token', event.data)
}, false);
前端通過 iframe
+postMessage()
方式,將同一份 Token
寫入到了多個域下的 LocalStorage
中,前端每次在向后端發(fā)送請求之前,都會主動從 LocalStorage
中讀取Token
并在請求中攜帶,這樣就實(shí)現(xiàn)了同一份Token
被多個域所共享
此種實(shí)現(xiàn)方式完全由前端控制,幾乎不需要后端參與,同樣支持跨域
三、流程
單點(diǎn)登錄的流程圖如下所示:

用戶訪問系統(tǒng)1的受保護(hù)資源,系統(tǒng)1發(fā)現(xiàn)用戶未登錄,跳轉(zhuǎn)至sso認(rèn)證中心,并將自己的地址作為參數(shù)
sso認(rèn)證中心發(fā)現(xiàn)用戶未登錄,將用戶引導(dǎo)至登錄頁面
用戶輸入用戶名密碼提交登錄申請
sso認(rèn)證中心校驗(yàn)用戶信息,創(chuàng)建用戶與sso認(rèn)證中心之間的會話,稱為全局會話,同時創(chuàng)建授權(quán)令牌
sso認(rèn)證中心帶著令牌跳轉(zhuǎn)會最初的請求地址(系統(tǒng)1)
系統(tǒng)1拿到令牌,去sso認(rèn)證中心校驗(yàn)令牌是否有效
sso認(rèn)證中心校驗(yàn)令牌,返回有效,注冊系統(tǒng)1
系統(tǒng)1使用該令牌創(chuàng)建與用戶的會話,稱為局部會話,返回受保護(hù)資源
用戶訪問系統(tǒng)2的受保護(hù)資源
系統(tǒng)2發(fā)現(xiàn)用戶未登錄,跳轉(zhuǎn)至sso認(rèn)證中心,并將自己的地址作為參數(shù)
sso認(rèn)證中心發(fā)現(xiàn)用戶已登錄,跳轉(zhuǎn)回系統(tǒng)2的地址,并附上令牌
系統(tǒng)2拿到令牌,去sso認(rèn)證中心校驗(yàn)令牌是否有效
sso認(rèn)證中心校驗(yàn)令牌,返回有效,注冊系統(tǒng)2
系統(tǒng)2使用該令牌創(chuàng)建與用戶的局部會話,返回受保護(hù)資源
用戶登錄成功之后,會與sso
認(rèn)證中心及各個子系統(tǒng)建立會話,用戶與sso
認(rèn)證中心建立的會話稱為全局會話
用戶與各個子系統(tǒng)建立的會話稱為局部會話,局部會話建立之后,用戶訪問子系統(tǒng)受保護(hù)資源將不再通過sso
認(rèn)證中心
全局會話與局部會話有如下約束關(guān)系:
局部會話存在,全局會話一定存在
全局會話存在,局部會話不一定存在
全局會話銷毀,局部會話必須銷毀
轉(zhuǎn)自https://www.cnblogs.com/smileZAZ/p/18202535
該文章在 2025/10/14 9:14:48 編輯過