前端需要了解的 SSO 與 CAS 知識

丁香園F2E發表於2017-11-07

不管是什麼公司,只要產品數量大於一個,那麼單點登入勢必是繞不過去的一個問題。作為前端程式設計師,我們對其雖然接觸不多,但適當的瞭解還是必要的。本文就來談談單點登入相關的問題。

前置知識

瞭解 SSO,最好具備以下知識。當然,如果不是特別熟,也不影響閱讀。

  • cookie及session
  • 瀏覽器同源策略及跨域
  • 瞭解登入系統的構成

什麼是 SSO 與 CAS?

SSO

SSO 是英文 Single Sign On 的縮寫,翻譯過來就是單點登入。顧名思義,它把兩個及以上個產品中的使用者登入邏輯抽離出來,達到只輸入一次使用者名稱密碼,就能同時登入多個產品的效果。

打個比方,SSO 和我們去迪士尼玩時購買的通票很像。前端需要了解的 SSO 與 CAS 知識

我們只要買一次通票,就可以玩所有遊樂場內的設施,而不需要在雲霄飛車或者摩天輪那裡重新買一次票。在這裡,買票就相當於登入認證,遊樂場就相當於使用一套 SSO 的公司,各種遊樂設施就相當於公司的各個產品。

前端需要了解的 SSO 與 CAS 知識

使用 SSO 的優點很明顯:

  • 提升使用者體驗。
就以我廠為例。我廠有兩個產品,丁香人才網和丁香園論壇,假如你是我廠使用者,肯定無法忍受登入丁香園論壇的時候輸入一次使用者名稱密碼,登入人才網又要輸入一次使用者名稱密碼吧?
  • 避免重複開發
假如你是我廠後端,每天任務都飽和的不行,肯定無法忍受到人才網開發一套登入邏輯,到論壇又開發一套登入邏輯吧?
  • 提升安全係數

假如你是我廠運維,發現了一個安全隱患需要緊急修復。你肯定無法忍受給茫茫多的產品後端都發一封郵件,責令修復吧?萬一漏了一個呢?

綜合看來,SSO 不僅是有用的,而且是必要的。

CAS

SSO 僅僅是一種架構,一種設計,而 CAS 則是實現 SSO 的一種手段。兩者是抽象與具體的關係。當然,除了 CAS 之外,實現 SSO 還有其他手段,比如簡單的 cookie。

CAS (Central Authentication Service)中心授權服務,本身是一個開源協議,分為 1.0 版本和 2.0 版本。1.0 稱為基礎模式,2.0稱為代理模式,適用於存在非 Web 應用之間的單點登入。本文只涉及 CAS 1.0,下文中將詳細介紹。

SSO 的演進與分類

下面詳述一下各種場景下的 SSO,它們之間是逐步升級,逐步複雜化的關係。

1.同域 SSO

如圖,同域 SSO 是最簡單的一種情況。

此時,兩個產品都是在一個域名下,單點登入是很自然的選擇。我們來捋一捋步驟,搞清楚這裡的步驟是理解後文的基礎,千萬不要跳過。

  1. 使用者訪問產品 a,向 後臺伺服器傳送登入請求。
  2. 登入認證成功,伺服器把使用者的登入資訊寫入 session。
  3. 伺服器為該使用者生成一個 cookie,並加入到 response header 中,隨著請求返回而寫入瀏覽器。該 cookie 的域設定為 dxy.cn。
  4. 下一次,當使用者訪問同域名的產品 b 時,由於 a 和 b 在同一域名下,也是 dxy.cn,瀏覽器會自動帶上之前的 cookie。此時後臺伺服器就可以通過該 cookie 來驗證登入狀態了。

實際上,這種場景就是最簡單最傳統的登入操作。雖然我們把產品 a 和 b 人為分開了,但由於它們在同域上,就算看成是同一產品的不同類目也未嘗不可。我們沒有設定獨立的 SSO 伺服器,因為業務後臺伺服器本身就足以承擔 SSO 的職能。

前端需要了解的 SSO 與 CAS 知識

2.同父域 SSO

同父域 SSO 是同域 SSO 的簡單升級,唯一的不同在於,伺服器在返回 cookie 的時候,要把cookie 的 domain 設定為其父域。

比如兩個產品的地址分別為 a.dxy.cn 和 b.dxy.cn,那麼 cookie 的域設定為 dxy.cn 即可。在訪問 a 和 b 時,這個 cookie 都能傳送到伺服器,本質上和同域 SSO 沒有區別。

3.跨域 SSO

可以看到,在上面兩種情況下,我們都沒有專門設定 SSO 伺服器。但是當兩個產品不同域時,cookie 無法共享,所以我們必須設定獨立的 SSO 伺服器了。這個時候,我們就是通過標準的 CAS 方案來實現 SSO 的。下面我們就來詳細介紹一下:


詳解CAS

CAS 1.0 協議定義了一組術語,一組票據,一組介面。

術語:

  • Client:使用者。
  • Server:中心伺服器,也是 SSO 中負責單點登入的伺服器。
  • Service:需要使用單點登入的各個服務,相當於上文中的產品 a/b。

介面:

  • /login:登入介面,用於登入到中心伺服器。
  • /logout:登出介面,用於從中心伺服器登出。
  • /validate:用於驗證使用者是否登入中心伺服器。
  • /serviceValidate:用於讓各個 service 驗證使用者是否登入中心伺服器。

票據

  • TGT:Ticket Grangting Ticket 

TGT 是 CAS 為使用者簽發的登入票據,擁有了 TGT,使用者就可以證明自己在 CAS 成功登入過。TGT 封裝了 Cookie 值以及此 Cookie 值對應的使用者資訊。當 HTTP 請求到來時,CAS 以此 Cookie 值(TGC)為 key 查詢快取中有無 TGT ,如果有的話,則相信使用者已登入過。


  • TGC:Ticket Granting Cookie
CAS Server 生成TGT放入自己的 Session 中,而 TGC 就是這個 Session 的唯一標識(SessionId),以 Cookie 形式放到瀏覽器端,是 CAS Server 用來明確使用者身份的憑證。


  • ST:Service Ticket 
ST 是 CAS 為使用者簽發的訪問某一 service 的票據。使用者訪問 service 時,service 發現使用者沒有 ST,則要求使用者去 CAS 獲取 ST。使用者向 CAS 發出獲取 ST 的請求,CAS 發現使用者有 TGT,則簽發一個 ST,返回給使用者。使用者拿著 ST 去訪問 service,service 拿 ST 去 CAS 驗證,驗證通過後,允許使用者訪問資源。


票據之間的關係如下圖。注意,PGTIOU, PGT, PT 是 CAS 2.0 中的內容,感興趣的同學可以自行了解。

前端需要了解的 SSO 與 CAS 知識

詳細步驟

看到這裡,是不是又有點暈了?沒關係,下面我們藉助一個簡單的場景,再來仔細捋一捋用 CAS 實現 SSO 的詳細步驟,順便加深理解之前提出的概念。

開始!

  1. 使用者訪問產品 a,域名是 www.a.cn。
  2. 由於使用者沒有攜帶在 a 伺服器上登入的 a cookie,所以 a 伺服器返回 http 重定向,重定向的 url 是 SSO 伺服器的地址,同時 url 的 query 中通過引數指明登入成功後,回跳到 a 頁面。重定向的url 形如 sso.dxy.cn/login?service=https%3A%2F%2Fwww.a.cn。
  3. 由於使用者沒有攜帶在 SSO 伺服器上登入的 TGC(看上面,票據之一),所以 SSO 伺服器判斷使用者未登入,給使用者顯示統一登入介面。使用者在 SSO 的頁面上進行登入操作。
  4. 登入成功後,SSO 伺服器構建使用者在 SSO 登入的 TGT(又一個票據),同時返回一個 http 重定向。這裡注意:
  • 重定向地址為之前寫在 query 裡的 a 頁面。
  • 重定向地址的 query 中包含 sso 伺服器派發的 ST
  • 重定向的 http response 中包含寫 cookie 的 header。這個 cookie 代表使用者在 SSO 中的登入狀態,它的值就是 TGC
  • 瀏覽器重定向到產品 a。此時重定向的 url 中攜帶著 SSO 伺服器生成的 ST
  • 根據 ST,a 伺服器向 SSO 伺服器傳送請求,SSO 伺服器驗證票據的有效性。驗證成功後,a 伺服器知道使用者已經在 sso 登入了,於是 a 伺服器構建使用者登入 session,記為 a session。並將 cookie 寫入瀏覽器。注意,此處的 cookie 和 session 儲存的是使用者在 a 伺服器的登入狀態,和 CAS 無關。
  • 之後使用者訪問產品 b,域名是 www.b.cn。
  •  由於使用者沒有攜帶在 b 伺服器上登入的 b cookie,所以 b 伺服器返回 http 重定向,重定向的 url 是 SSO 伺服器的地址,去詢問使用者在 SSO 中的登入狀態。
  • 瀏覽器重定向到 SSO。注意,第 4 步中已經向瀏覽器寫入了攜帶 TGC 的cookie,所以此時 SSO 伺服器可以拿到,根據 TGC 去查詢 TGT,如果找到,就判斷使用者已經在 sso 登入過了。
  • SSO 伺服器返回一個重定向,重定向攜帶 ST。注意,這裡的 ST 和第4步中的 ST 是不一樣的,事實上,每次生成的 ST 都是不一樣的。
  • 瀏覽器帶 ST 重定向到 b 伺服器,和第 5 步一樣。
  • b 伺服器根據票據向 SSO 伺服器傳送請求,票據驗證通過後,b 伺服器知道使用者已經在 sso 登入了,於是生成 b session,向瀏覽器寫入 b cookie。
  • 前端需要了解的 SSO 與 CAS 知識


    如圖所示,至此,整個登入流程結束。之後當使用者訪問 a 或者 b 後,直接會攜帶 a cookie/b cookie,就不用再向 SSO 確認了。

    實際開發時,可以根據 CAS 增加更多的判斷邏輯,比如,在收到CAS Server簽發的ST後,如果 ST 被 hacker 竊取,並且 client 本身沒來得及去驗證 ST,被 hacker 搶先一步驗證 ST,怎麼解決。此時就可以在申請 ST 時新增額外驗證因子(如ip、sessionId等)。


    參考閱讀:



    相關文章