切換語言為:簡體
單點登入是什麼以及如何實現單點登入

單點登入是什麼以及如何實現單點登入

  • 爱糖宝
  • 2024-09-20
  • 2035
  • 0
  • 0

一:單點登入是什麼

單點登入(Single Sign On),簡稱為 SSO,是目前比較流行的企業業務整合的解決方案之一

SSO的定義是在多個應用系統中,使用者只需要登入一次就可以訪問所有相互信任的應用系統SSO 一般都需要一個獨立的認證中心(passport),子系統的登入均得透過 passport ,子系統本身將不參與登入操作

當一個系統成功登入以後,passport 將會頒發一個令牌給各個子系統,子系統可以拿著令牌會獲取各自的受保護資源,爲了減少頻繁認證,各個子系統在被 passport 授權以後,會建立一個區域性會話,在一定時間內可以無需再次向 passport發起認證

單點登入是什麼以及如何實現單點登入

上圖有四個系統,分別是Application1Application2Application3、和SS0當Application1Application2Application3需要登入時,將跳到 SS0 系統,SS0 系統完成登入,其他的應用系統也就隨之登入了

舉個例子

淘寶、天貓都屬於阿里旗下,當用戶登入淘寶後,再開啟天貓,系統便自動幫使用者登入了天貓,這種現象就屬於單點登入

二:如何實現

2.1.同域名下的單點登入

cookiedomain 屬性設定為當前域的父域,並且父域的 cookie 會被子域所共享。 path 屬性預設為 web 應用的上下文路徑

利用 Cookie 的這個特點,沒錯,我們只需要將Cookiedomain 屬性設定為父域的域名(主域名),同時將Cookiepath屬性設定為根路徑,將SessionID(或Token)儲存到父域中。這樣所有的子域應用就都可以訪問到這個Cookie

不過這要求應用系統的域名需建立在一個共同的主域名之下,如 tieba.baidu.commap.baidu.com ,它們都建立在baidu.com 這個主域名之下,那麼它們就可以透過這種方式來實現單點登入

2.2.基於認證中心的SSO

如果是不同域的情況下,Cookie 是不共享的,這裏我們可以部署一個認證中心,用於專門處理登入請求的獨立的 Web 服務 使用者統一在認證中心進行登入,登入成功後,認證中心記錄使用者的登入狀態,並將token寫入Cookie (注意這個Cookie 是認證中心的,應用系統是訪問不到的)

應用系統檢查當前請求有沒有Token,如果沒有,說明使用者在當前系統中尚未登入,那麼就將頁面跳轉至認證中心

由於這個操作會將認證中心的CookieCookie 知道使用者是自動帶過去,因此,認證中心能夠根據否已經登入過了

如果認證中心發現使用者尚未登入,則返回登入頁面,等待使用者登入

如果發現使用者已經登入過了,就不會讓使用者再次登入了,而是會跳轉回目標URL,並在跳轉前生成一個 Token,拼接在目標 URL 的後面,回傳給目標應用系統

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

此種實現方式相對複雜,支援跨域,擴充套件性好,是單點登入的標準做法

2.3.基於LocalStorage的SSO

可以選擇將SessionID(或Token )儲存到瀏覽器的 LocalStorage 中,讓前端在每次向後端傳送請求時,主動將LocalStorage 的資料傳遞給服務端

這些都是由前端來控制的,後端需要做的僅僅是在使用者登入成功後,將SessionID(或 Token)放在響應體中傳遞給前端

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

關鍵程式碼如下:

// 獲取 token
var token =result.data.token;

//動態建立一個不可見的iframe,在iframe中載入一個跨域HTMLvar 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中繫結一個事件監聽器,當事件被觸發時,把接收到的token資料寫入localstorage

window.addEventListener('message',function(event){
    localStorage.setItem(token',event.data)
 },false);

前端透過 iframe+postMessage()方式,將同一份 Token 寫入到了多個域下的 LocalStorage 中,前端每次在向後端傳送請求之前,都會主動從LocalStorage中讀取 Token 並在請求中攜帶,這樣就實現了同一份 Token 被多個域所共享

此種實現方式完全由前端控制,幾乎不需要後端參與,同樣支援跨域

三:流程

單點登入流程:

單點登入是什麼以及如何實現單點登入

  • 使用者訪問系統1的受保護資源,系統1發現使用者未登入,跳轉至sso認證中心,並將自己的地址作為引數

  • sso認證中心發現使用者未登入,將使用者引導至登入頁面

  • 使用者輸入使用者名稱密碼提交登入申請

  • sso認證中心校驗使用者資訊,建立使用者與sso認證中心之間的會話,稱為全域性會話,同時建立授權令牌

  • sso認證中心帶著令牌跳轉會最初的請求地址(系統1)

  • 系統1拿到令牌,去sso認證中心校驗令牌是否有效

  • sso認證中心校驗令牌,返回有效,註冊系統1

  • 系統1使用該令牌建立與使用者的會話,稱為區域性會話,返回受保護資源

  • 使用者訪問系統2的受保護資源

  • 系統2發現使用者未登入,跳轉至sso認證中心,並將自己的地址作為引數

  • sso認證中心發現使用者已登入,跳轉回系統2的地址,並附上令牌

  • 系統2拿到令牌,去sso認證中心校驗令牌是否有效

  • sso認證中心校驗令牌,返回有效,註冊系統2系統2

  • 使用該令牌建立與使用者的區域性會話,返回受保護資源

使用者登入成功之後,會與sso認證中心及各個子系統建立會話,使用者與sso認證中心建立的會話稱為全域性會話

使用者與各個子系統建立的會話稱為區域性會話,區域性會話建立之後,使用者訪問子系統受保護資源將不再透過 sso 認證中心 全域性會話與區域性會話有如下約束關係:

  • 區域性會話存在,全域性會話一定存在

  • 全域性會話存在,區域性會話不一定存在

  • 全域性會話銷燬,區域性會話必須銷燬

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.