鬆哥手把手教你入門 Spring Boot + CAS 單點登入

江南一點雨發表於2020-06-01

在微服務以及分散式系統中,單點登入變得越來越普遍,鬆哥之前也有兩篇文章和大家介紹過單點登入的方案:

這兩種方案中,JWT 存在一個登出登入的問題,要費點功夫解決。@EnableOAuth2Sso 註解這種方案不存在登出登入的問題,但是又不像 JWT 那麼靈活。

沒有銀彈!

在實際專案中,我們只能根據自己的實際需求,看一看哪一種方案更適合自己,然後在此基礎上進行改造!

現在我們在 Spring Cloud Security 中使用 OAuth2+JWT 或者使用 @EnableOAuth2Sso 註解比以前要方便很多了,鬆哥也是最近才把專案切換到 Spring Cloud Security 技術棧上面來,在這之前,單點登入用的更多的是 CAS 單點登入。相信有不少小夥伴在公司裡可能也還是使用了 CAS 單點登入這種方案,今天鬆哥就來花點時間,和大家聊聊 CAS+Spring Security 實現單點登入,這種方案到底該怎麼玩。

可能會連續幾篇文章來介紹 CAS 單點登入,本文先來說說理論和登入流程。另外,由於 CAS 和 Spring Cloud OAuth2 在某些方面具有一定的相似性,所以強烈建議大家先看一看鬆哥的 OAuth2 系列教程,再來閱讀本文就會輕鬆很多(公眾號後臺回覆 OAuth2 有相關教程)。

本文是 Spring Security 系列第 23 篇,閱讀本系列前面的文章有助於更好的理解本文:

  1. 挖一個大坑,Spring Security 開搞!
  2. 鬆哥手把手帶你入門 Spring Security,別再問密碼怎麼解密了
  3. 手把手教你定製 Spring Security 中的表單登入
  4. Spring Security 做前後端分離,我們就別做頁面跳轉了!統統 JSON 互動
  5. Spring Security 中的授權操作原來這麼簡單
  6. Spring Security 如何將使用者資料存入資料庫?
  7. Spring Security+Spring Data Jpa 強強聯手,安全管理只有更簡單!
  8. Spring Boot + Spring Security 實現自動登入功能
  9. Spring Boot 自動登入,安全風險要怎麼控制?
  10. 在微服務專案中,Spring Security 比 Shiro 強在哪?
  11. SpringSecurity 自定義認證邏輯的兩種方式(高階玩法)
  12. Spring Security 中如何快速檢視登入使用者 IP 地址等資訊?
  13. Spring Security 自動踢掉前一個登入使用者,一個配置搞定!
  14. Spring Boot + Vue 前後端分離專案,如何踢掉已登入使用者?
  15. Spring Security 自帶防火牆!你都不知道自己的系統有多安全!
  16. 什麼是會話固定攻擊?Spring Boot 中要如何防禦會話固定攻擊?
  17. 叢集化部署,Spring Security 要如何處理 session 共享?
  18. 鬆哥手把手教你在 SpringBoot 中防禦 CSRF 攻擊!so easy!
  19. 要學就學透徹!Spring Security 中 CSRF 防禦原始碼解析
  20. Spring Boot 中密碼加密的兩種姿勢!
  21. Spring Security 要怎麼學?為什麼一定要成體系的學習?
  22. Spring Security 兩種資源放行策略,千萬別用錯了!

1.什麼是 CAS

CAS 全稱叫做中央認證服務,英文是 Central Authentication Service。

這是由耶魯大學發起的一個開源專案,目的是幫助 Web 應用系統構建一種可靠的單點登入解決方案,從目前企業實際專案來看,CAS 還是非常受歡迎的一種單點登入解決方案。

1.1 CAS 架構

CAS 分為兩部分:

  • 一個是 CAS Server,這是單點驗證服務,作用類似於我們OAuth2+JWT 方案中的授權伺服器,用來校驗使用者名稱/密碼等,一般來說都是獨立部署。
  • 另一個則是 CAS Client,相當於就是一個一個的(微)服務。

我們來看 CAS 的官方給出的一個架構圖:

可以看到,使用者訪問的是 CAS Clients,CAS Clients 和 CAS Server 之間的通訊支援多種協議,CAS Server 處理具體的認證事宜,CAS Server 對資料來源的支援也非常多樣化。

CAS Client 支援的平臺有:

  • Apache httpd Server (mod_auth_cas module)
  • Java (Java CAS Client)
  • .NET (.NET CAS Client)
  • PHP (phpCAS)
  • Perl (PerlCAS)
  • Python (pycas)
  • Ruby (rubycas-client)

CAS 支援的通訊協議有:

  • CAS (versions 1, 2, and 3)
  • SAML 1.1 and 2
  • OpenID Connect
  • OpenID
  • OAuth 2.0
  • WS Federation

從圖中也可以看出 CAS 支援多種不同的認證機制,具體有:

  • JAAS
  • LDAP
  • RDBMS
  • SPNEGO
  • ...

1.2 三個概念

在 CAS 的整個登入過程中,有三個重要的概念,這裡我先來和大家捋一捋。

  1. TGT:TGT 全稱叫做 Ticket Granting Ticket,這個相當於我們平時所見到的 HttpSession 的作用,使用者登入成功後,使用者的基本資訊,如使用者名稱、登入有效期等資訊,都將儲存在此。
  2. TGC:TGC 全稱叫做 Ticket Granting Cookie,TGC 以 Cookie 的形式儲存在瀏覽器中,根據 TGC 可以幫助使用者找到對應的 TGT,所以這個 TGC 有點類似與會話 ID。
  3. ST:ST 全稱是 Service Ticket,這是 CAS Sever 通過 TGT 給使用者發放的一張票據,使用者在訪問其他服務時,發現沒有 Cookie 或者 ST ,那麼就會 302 到 CAS Server 獲取 ST,然後會攜帶著 ST 302 回來,CAS Client 則通過 ST 去 CAS Server 上獲取使用者的登入狀態。

2.CAS 登入流程

接下來我們通過一張官方給出的流程圖來看下 CAS 登入過程是什麼樣子的!

這張圖其實畫的比較清楚了,我再用文字和大家解釋下:

術語:應用1、應用2 分別表示被保護的應用。

  1. 使用者通過瀏覽器訪問應用1,應用1 發現使用者沒有登入,於是返回 302,並且攜帶上一個 service 引數,讓使用者去 CAS Server 上登入。
  2. 瀏覽器自動重定向到 CAS Server 上,CAS Server 獲取使用者 Cookie 中攜帶的 TGC,去校驗使用者是否已經登入,如果已經登入,則完成身份校驗(此時 CAS Server 可以根據使用者的 TGC 找到 TGT,進而獲取使用者的資訊);如果未登入,則重定向到 CAS Server 的登入頁面,使用者輸入使用者名稱/密碼,CAS Server 會生成 TGT,並且根據 TGT 簽發一個 ST,再將 TGC 放在使用者的 Cookie 中,完成身份校驗。
  3. CAS Server 完成身份校驗之後,會將 ST 拼接在 service 中,返回 302,瀏覽器將首先將 TGC 存在 Cookie 中,然後根據 302 的指示,攜帶上 ST 重定向到應用1。
  4. 應用1 收到瀏覽器傳來的 ST 之後,拿去 CAS Server 上校驗,去判斷使用者的登入狀態,如果使用者登入合法,CAS Server 就會返回使用者資訊給 應用1。
  5. 瀏覽器再去訪問應用2,應用2 發現使用者未登入,重定向到 CAS Server。
  6. CAS Server 發現此時使用者實際上已經登入了,於是又重定向回應用2,同時攜帶上 ST。
  7. 應用2 拿著 ST 去 CAS Server 上校驗,獲取使用者的登入資訊。

在整個登入過程中,瀏覽器分別和 CAS Server、應用1、應用2 建立了會話,其中,和 CAS Server 建立的會話稱之為全域性會話,和應用1、應用2 建立的會話稱之為區域性會話;一旦區域性會話成功建立,以後使用者再去訪問應用1、應用2 就不會經過 CAS Server 了。

3.CAS Server 搭建

說了這麼多,來點實際的。

由於整個 CAS 單點登入做起來還比較麻煩,我們一步一步來,今天我先來教大家把 CAS Server 搭建起來。

3.1 版本選擇

目前最新的 CAS Server 是 6.x,這個是基於 gradle 來構建的,考慮到很多小夥伴可能不熟悉 gradle 操作,因此這裡我選擇 5.3 的版本,該版本基於大家熟悉的 maven 來構建。

官方為我們提供了構建 CAS Server 的模版,地址是:https://github.com/apereo/cas...

我們在分支中選擇 5.3 版本下載:

或者直接 clone 下來,然後切換到 5.3 這個分支也可以。這個應該就不用我教大家了吧,相信小夥伴們都能自己搞定。

3.2 HTTPS 證照

CAS Server 從版本 4 開始,要使用 HTTPS 通訊,所以我們得提前準備 HTTPS 證照。公司裡的專案的話,需要購買 HTTPS 證照,自己玩的話也可以從雲服務廠商那裡申請到免費的 HTTPS 證照。

現在我們在本地測試,直接利用 JDK 自帶的 keytool 工具,自己生成一個 HTTPS 證照即可。

生成命令如下:

keytool -genkey -alias casserver -keyalg RSA -keystore ./keystore
  • -alias 表示生成的證照別名
  • -keyalg 表示生成證照使用的演算法
  • -keystore 表示生成證照的存放位置

證照在執行的時候,需要給一個金鑰庫口令,這個大家隨意給出即可,但是給出了多少要自己記著。另外,在 What is your first and last name? 選項中,需要填入 CAS Server 的域名,這點切記

如此之後,我們的 HTTPS 證照就有了,雖然這個證照不被各大廠商認可,但是自己做練習夠用了。

3.3 配置並啟動

接下來進行配置。

我們在下載的 cas-overlay-template 專案中,新建 src/main/resources 目錄,並將 overlays/org.apereo.cas.cas-server-webapp-tomcat-5.3.14/WEB-INF/classes/application.properties 檔案和剛剛生成的 keystore 檔案拷貝進來:

然後修改 application.properties ,主要配置一下 keystore 的位置和金鑰,如下:

server.ssl.key-store=classpath:keystore
server.ssl.key-store-password=111111
server.ssl.key-password=111111

配置完成後,在專案根目錄下執行如下命令啟動專案:

./build.sh bootrun

根據個人網速,第一次啟動可能會非常漫長,耐心等待即可。

啟動過程中,也可能會報錯,但是不用管,如果看到 ready 圖示,就表示啟動成功了:

3.4 測試

啟動成功後,瀏覽器輸入 https://cas.javaboy.org:8443/cas/login 就可以進入登入頁面了(注意是 https 哦):

預設的使用者名稱是 casuser,密碼是 Mellon,輸入使用者名稱密碼就可以登入了。

預設的使用者名稱/密碼也可以在 application.properties 檔案中修改,該檔案的最後一行:

cas.authn.accept.users=casuser::Mellon

修改完後,重啟專案即可生效。

4.小結

今天主要和小夥伴聊一下 CAS 的基本概念,然後我們順手搭建一個 CAS Server 出來,感興趣的小夥伴可以動手試一試哦~,下篇文章我們來看如何用 Spring Boot 開發 CAS 客戶端~

好啦,如果小夥伴們覺得有收穫,記得點個在看鼓勵下鬆哥哦~

相關文章