在微服務以及分散式系統中,單點登入變得越來越普遍,鬆哥之前也有兩篇文章和大家介紹過單點登入的方案:
這兩種方案中,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 篇,閱讀本系列前面的文章有助於更好的理解本文:
- 挖一個大坑,Spring Security 開搞!
- 鬆哥手把手帶你入門 Spring Security,別再問密碼怎麼解密了
- 手把手教你定製 Spring Security 中的表單登入
- Spring Security 做前後端分離,我們就別做頁面跳轉了!統統 JSON 互動
- Spring Security 中的授權操作原來這麼簡單
- Spring Security 如何將使用者資料存入資料庫?
- Spring Security+Spring Data Jpa 強強聯手,安全管理只有更簡單!
- Spring Boot + Spring Security 實現自動登入功能
- Spring Boot 自動登入,安全風險要怎麼控制?
- 在微服務專案中,Spring Security 比 Shiro 強在哪?
- SpringSecurity 自定義認證邏輯的兩種方式(高階玩法)
- Spring Security 中如何快速檢視登入使用者 IP 地址等資訊?
- Spring Security 自動踢掉前一個登入使用者,一個配置搞定!
- Spring Boot + Vue 前後端分離專案,如何踢掉已登入使用者?
- Spring Security 自帶防火牆!你都不知道自己的系統有多安全!
- 什麼是會話固定攻擊?Spring Boot 中要如何防禦會話固定攻擊?
- 叢集化部署,Spring Security 要如何處理 session 共享?
- 鬆哥手把手教你在 SpringBoot 中防禦 CSRF 攻擊!so easy!
- 要學就學透徹!Spring Security 中 CSRF 防禦原始碼解析
- Spring Boot 中密碼加密的兩種姿勢!
- Spring Security 要怎麼學?為什麼一定要成體系的學習?
- 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 的整個登入過程中,有三個重要的概念,這裡我先來和大家捋一捋。
- TGT:TGT 全稱叫做 Ticket Granting Ticket,這個相當於我們平時所見到的 HttpSession 的作用,使用者登入成功後,使用者的基本資訊,如使用者名稱、登入有效期等資訊,都將儲存在此。
- TGC:TGC 全稱叫做 Ticket Granting Cookie,TGC 以 Cookie 的形式儲存在瀏覽器中,根據 TGC 可以幫助使用者找到對應的 TGT,所以這個 TGC 有點類似與會話 ID。
- 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 發現使用者沒有登入,於是返回 302,並且攜帶上一個 service 引數,讓使用者去 CAS Server 上登入。
- 瀏覽器自動重定向到 CAS Server 上,CAS Server 獲取使用者 Cookie 中攜帶的 TGC,去校驗使用者是否已經登入,如果已經登入,則完成身份校驗(此時 CAS Server 可以根據使用者的 TGC 找到 TGT,進而獲取使用者的資訊);如果未登入,則重定向到 CAS Server 的登入頁面,使用者輸入使用者名稱/密碼,CAS Server 會生成 TGT,並且根據 TGT 簽發一個 ST,再將 TGC 放在使用者的 Cookie 中,完成身份校驗。
- CAS Server 完成身份校驗之後,會將 ST 拼接在 service 中,返回 302,瀏覽器將首先將 TGC 存在 Cookie 中,然後根據 302 的指示,攜帶上 ST 重定向到應用1。
- 應用1 收到瀏覽器傳來的 ST 之後,拿去 CAS Server 上校驗,去判斷使用者的登入狀態,如果使用者登入合法,CAS Server 就會返回使用者資訊給 應用1。
- 瀏覽器再去訪問應用2,應用2 發現使用者未登入,重定向到 CAS Server。
- CAS Server 發現此時使用者實際上已經登入了,於是又重定向回應用2,同時攜帶上 ST。
- 應用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 客戶端~
好啦,如果小夥伴們覺得有收穫,記得點個在看鼓勵下鬆哥哦~