天天看點

多站點單點登入實作方案

今天寫一篇關于多域名下單點登入的實作。

有這麼個場景,公司下有多個不同域名的站點,我們期望使用者在任意一個站點下登入後,在打開另外幾個站點時,也是已經登入的狀态,這麼一過程就是單點登入。

因為多個站點都是用的同一套使用者體系,是以單點登入可以免去使用者重複登入,讓使用者在站點切換的時候更加流暢,甚至是無感覺。

單點登入所要實作的就是,某一站點登入後,将其登入态會同步到其他另外幾個站點。

我們分兩部分,先說單個站點的登入流程,在說同步登入态的流程。

登入相關架構

  • 服務端采用

    nodejs

    ,緩存采用

    redis

  • 使用者登入憑證采用基于

    session

    cookies

    維系,采用

    cookie

    作為登入憑證是目前比較主流的方式。
  • session

    資訊用

    redis

    承載,從資料層面上看,

    redis

    中存儲

    session

    對象的

    key

    便是

    cookie

    中的

    value

  • key

    是由

    UUID

    生成的唯一辨別
  • 為了保證

    session

    cookie

    保持對應,

    session

    對象建立與修改都會觸發服務端往浏覽器寫入

    cookie

登入流程

我們先看單個站點的登入流程

  1. 使用者首次打開站點,服務端生成

    session

    對象,此時

    session

    中沒有使用者資訊,同時服務端往浏覽器寫入

    cookie

  2. 使用者觸發登入操作
  3. 服務端校驗參數處理登入邏輯後,生成使用者資訊,将使用者資訊寫入

    session

    對象,更新緩存

    redis

    我們來畫個圖,如下
多站點單點登入實作方案

同步登入态

一個站點完成登入後,接下來就是如何讓其他站點也擁有登入态。

既然登入态是由

cookie

session

決定的,而

cookie

又是由

session

寫入的,那麼也就是說,隻要把

session

同步到其它站點,其它站點隻要擷取到

session

後,就可以在該域名建立或更新

cookie

,這樣一來,兩個不同域名下的站點就擁有相同的登入資訊了。

是以,同步登入态其實就是,如何同步

session

的問題。

而我們的

session

是采用

redis

作為載體,那麼其他站點隻要能擷取到

redis

中存儲的使用者資訊,不就可以建立自己的

session

對象了麼?

沒錯!如何同步

session

的問題,就變成了如何讓其他站點從

redis

中擷取使用者資訊,也就是如何讓其他站點知道存儲該使用者資訊的

redis key

到了這一步,我們需要解決的問題就很明顯啦:如何在不同站點間傳輸使用者憑證。

為便于描述,我們假設有兩個站點,分别為A站點和B站點。因為A、B站點的域名不同,基于同源政策,

cookie

是沒法共享的,是以我們采取主動請求的方式,将使用者唯一憑證通過接口傳過去。大緻流程如下

  1. A站點完成登入邏輯後,将使用者憑證傳回到浏覽器,為了安全性,在傳輸憑證前,對憑證進行加密,可采用

    AES

    或者

    RSA

  2. A站點的用戶端擷取到憑證後,調用B站點提供的同步登入态接口,将憑證傳過去
  3. B站點的服務端擷取到憑證,解密,查詢緩存中的使用者資訊,建立

    session

    對象,寫入B站點域名下的

    cookie

    資訊
  4. B站點的登入态同步完成。

基于上圖,我們完善同步的時序圖

多站點單點登入實作方案

同步登入态的場景

上面描述的是當使用者首次登入時的同步流程,還需要考慮其他場景,比如,B站點獲得的登入态失效了,這時候通路B站點頁面,就需要在一次前往A站點同步登入态。

B站點上的頁面分為兩種,一種是需要登入态才可以通路的,一種是不需要登入态就可以通路的。

第一種情況下,需要重定向到A站點,可為啥要繞回去A站點呢?因為此時我們也不知道A站點的登入态是否也失效了,是以需要回到A站點判斷A站點目前的登入态,若A站點登入态也失效了,那麼就去登陸頁進行重新登入,若A站點是有登陸态的,那麼隻要在做一次同步登入态的操作即可。

第二種情況,雖然B頁面不需要登入态就可以檢視,但是企業網站往往會在頁面的head部分标記使用者的登入态,是以為了讓這部分的顯示正常,我們在目前頁面異步的去更新登入态即可。

多站點單點登入實作方案

若有其他場景,處理的邏輯與這個類似,本質無非就是在擷取一次憑證,重新更新站點緩存。

跨域請求

因為要在A站點請求B域名下的接口,是以會有跨域問題,跨域問題常用的解決方式有如下幾種

  1. JSONP

    很常見很通用的一種方式
  2. Image

    利用

    Image src

    可以繞過同源政策,是以通過建構一個

    Image

    發送給請求也是可行的,同時服務端也不需要做太多修改。
  3. CORS

    老的浏覽器就沒法支援,需要在服務端設定

    Access-Control-Allow-Origin

    ,允許任何域或指定的域發起的請求都可以擷取目前伺服器的資料。

小結

文章主要是已方案為主,就不放上詳細的代碼了,其實有了具體方案,代碼的實作就不難啦。

多站點單點登入肯定還有其他優秀的解決方案,歡迎小夥伴們評論區一起交流探讨呀~

繼續閱讀