CAS單點登錄(十一)——單點退出
在前面我們講解了CAS的單點登錄客戶端接入,對於CAS的登錄有了更清楚的了解,今天我們講解一下在CAS中的單點退出問題。
首先我們要明白單點退出(單點注銷)與注銷的區別:
其實官方文檔也給我們詳細的解釋了:
注銷:
應用程序注銷 - 結束單個應用程序會話
CAS注銷 - 結束CAS SSO會話
1
2
請注意,在簡單的情況下,每種情況下的注銷操作對另一種情況都沒有影響。
而單點注銷(SLO):
當CAS配置為SLO時,它會嘗試向SSO會話期間請求對CAS進行身份驗證的每個應用程序發送注銷消息。CAS旨在支持單點注銷:這意味着除了自己的SSO會話之外,它還能夠使客戶端應用程序會話無效。
對應CAS單點退出的流程原理可以查看CAS單點登錄(一)——初識SSO當時在文章中也有講解。
同樣的我們再來分析一下具體的流程:
用戶向系統1發起注銷請求
系統1根據用戶與系統1建立的會話id拿到令牌,向SSO認證中心發起注銷請求
SSO認證中心校驗令牌有效,銷毀全局會話,同時取出所有用此令牌注冊的系統地址
SSO認證中心向所有注冊系統發起注銷請求
各注冊系統接收SSO認證中心的注銷請求,銷毀局部會話
SSO認證中心引導用戶至登錄頁面
第5條中就詳細分析了,當多個系統接入到CAS中時,單點退出時各注冊系統接收SSO認證中心的注銷請求,銷毀局部會話。
默認CAS單點退出(單點注銷)是開啟的,我們可以手動配置關閉或啟用。
##
# Single Logout配置
#
cas.slo.disabled=false
cas.slo.asynchronous=true
1
2
3
4
5
CAS單點注銷主要支持下面兩種方式:
1、Back Channel
CAS服務端直接向各服務客戶端發送HTTP POST消息。這是向服務執行通知的傳統方式。
2、Front Channel
CAS 通過一個異步的AJAX方式的GET請求,通過JSONP去驗證各客戶端服務,來使得各客戶端的session無效。
注意:該方式不一定適用所有客戶端,必須要確保客戶端支持該方式。
CAS單點注銷請求默認是在后台通過logoutType的屬性配置好了的,默認為LogoutType.BACK_CHANNEL。
單個服務配置單點注銷:
使用CAS注冊的應用程序可以選擇通過服務管理組件單獨控制單個注銷行為。服務注冊表中的每個注冊服務都將包含描述如何提交注銷請求的配置。此行為通過logoutType屬性進行控制,該屬性允許指定是應通過后/前通道提交注銷請求還是為此應用程序關閉注銷請求。關閉注銷請求可以將logoutType設置為NONE。
{
"@class" : "org.apereo.cas.services.RegexRegisteredService",
"serviceId" : "^(https|imaps|http)://.*",
"name" : "web",
"id" : 10000001,
"evaluationOrder" : 10,
"accessStrategy" : {
"@class" : "org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy",
"enabled" : true,
"ssoEnabled" : true
},
"attributeReleasePolicy": {
"@class": "org.apereo.cas.services.ReturnAllAttributeReleasePolicy"
},
"theme": "anumbrella",
"logoutType" : "BACK_CHANNEL"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
注銷請求的請求路徑配置,我們可以為每個服務配置請求路徑,這樣實現了更大的靈活性。
{
"@class" : "org.apereo.cas.services.RegexRegisteredService",
"serviceId" : "^(https|imaps|http)://.*",
"name" : "web",
"id" : 10000001,
"evaluationOrder" : 10,
"accessStrategy" : {
"@class" : "org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy",
"enabled" : true,
"ssoEnabled" : true
},
"attributeReleasePolicy": {
"@class": "org.apereo.cas.services.ReturnAllAttributeReleasePolicy"
},
"theme": "anumbrella",
"logoutType" : "BACK_CHANNEL",
"logoutUrl" : "https://client.anumbrella.net/logout"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
我們依然使用前面的client-demo來講解CAS單點注銷,注意:在CAS 5.3.x版本退出加上service參數,不會自動跳轉,需要在application.properties中配置一下。
##
# Logout配置
#
cas.logout.followServiceRedirects=true
1
2
3
4
我們client-demo的控制器中添加service參數測試:
@GetMapping("/logout")
public String logout(HttpSession session){
session.removeAttribute(WebSecurityConfig.SESSION_KEY);
return "redirect:https://sso.anumbrella.net:8443/cas/logout?service=https://client.anumbrella.net:9443/";
}
1
2
3
4
5
6
當我們主動退出后,自動跳轉到登錄頁面。
我們啟動一個CAS客戶端服務cas-management,在里面可以查看到CAS退出的相關配置。
這里我們將logoutUrl設置為http://172.16.67.230:8000/logout,具體地址為我本機調試IP,通過MAC終端調試工具 nc netcat來監聽端口8000,服務端發送給我們的被動退出請求,方法為POST。
sudo nc -l 0.0.0.0 8000
1
當然還可以使用Wireshark來捕獲服務端發送給我們請求,注意:Wireshark抓取數據包的時候發現只能抓取別的機器上的數據包,如果是本機的服務則發現好像抓不到。需要進行一定的配置才行,所以這里我使用的是nc netcat 工具。
目前我們啟動了兩個客戶端,一個服務端。我們點擊client-demo注銷。
在服務端日志中我們發現,發送了2次請求。
在命令端我們接收到服務端的POST請求。
然后我們便可以根據logoutRequst請求的參數中去銷毀各個服務端的session,一般情況是session的鍵值對,鍵為st票據,拿到鍵我們就能刪除具體的session。當然不同的客戶端接入情況不一樣,具體看保存session時是如何做的。
比如上面的logoutRequst的數據形式如下:我們拿到的就是ST-21-qK6bcCxu4iJZBBGtG0MtsNsgJ40anumbrelladeiMac。
<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="LR-20-gJ8SYdbM4Ycm-xG3Dve-p3qA" Version="2.0" IssueInstant="2019-04-07T15:40:02Z">
<saml:NameID xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">@NOT_USED@</saml:NameID>
<samlp:SessionIndex>ST-21-qK6bcCxu4iJZBBGtG0MtsNsgJ40anumbrelladeiMac</samlp:SessionIndex>
</samlp:LogoutRequest>
1
2
3
4
這里我只是簡單演示了一下退出服務端發送的請求,如果我們CAS系統接入很多客戶端,具體客戶端在不同的地址,我們就可以配置自己相應的logoutUrl,然后在被動退出時在POST監聽地址中銷毀掉session即可。
代碼實例:Chapter10
參考
https://apereo.github.io/cas/5.3.x/installation/Logout-Single-Signout.html
https://apereo.github.io/cas/5.3.x/protocol/CAS-Protocol-Specification.html
————————————————
版權聲明:本文為CSDN博主「Anumbrella」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/anumbrella/article/details/89069445