在前面我们讲解了CAS的单点登录客户端接入,对于CAS的登录有了更清楚的了解,今天我们讲解一下在CAS中的单点退出问题。
首先我们要明白单点退出(单点注销)与注销的区别:
其实官方文档也给我们详细的解释了:
注销:
应用程序注销 - 结束单个应用程序会话
CAS注销 - 结束CAS SSO会话
请注意,在简单的情况下,每种情况下的注销操作对另一种情况都没有影响。
而单点注销(SLO):
当CAS配置为SLO时,它会尝试向SSO会话期间请求对CAS进行身份验证的每个应用程序发送注销消息。CAS旨在支持单点注销:这意味着除了自己的SSO会话之外,它还能够使客户端应用程序会话无效。
对应CAS单点退出的流程原理可以查看CAS单点登录(一)——初识SSO当时在文章中也有讲解。
同样的我们再来分析一下具体的流程:
第5条中就详细分析了,当多个系统接入到CAS中时,单点退出时各注册系统接收SSO认证中心的注销请求,销毁局部会话。
默认CAS单点退出(单点注销)是开启的,我们可以手动配置关闭或启用。
##
# Single Logout配置
#
cas.slo.disabled=false
cas.slo.asynchronous=true
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"
}
注销请求的请求路径配置,我们可以为每个服务配置请求路径,这样实现了更大的灵活性。
{
"@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"
}
我们依然使用前面的client-demo来讲解CAS单点注销,注意:在CAS 5.3.x版本退出加上service参数,不会自动跳转,需要在application.properties中配置一下。
##
# Logout配置
#
cas.logout.followServiceRedirects=true
我们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/";
}
当我们主动退出后,自动跳转到登录页面。
我们启动一个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
当然还可以使用Wireshark来捕获服务端发送给我们请求,注意:Wireshark抓取数据包的时候发现只能抓取别的机器上的数据包,如果是本机的服务则发现好像抓不到。需要进行一定的配置才行,所以这里我使用的是nc netcat 工具。
目前我们启动了两个客户端,一个服务端。我们点击client-demo注销。
在服务端日志中我们发现,发送了2次请求。
在命令端我们接收到服务端的POST请求。
然后我们便可以根据logoutRequst请求的参数中去销毁各个服务端的session,一般情况是session的键值对,键为st票据,拿到键我们就能删除具体的session。当然不同的客户端接入情况不一样,具体看保存session时是如何做的。
比如上面的logoutRequst的数据形式如下:我们拿到的就是ST-21-qK6bcCxu4iJZBBGtG0MtsNsgJ40anumbrelladeiMac
。
@NOT_USED@
ST-21-qK6bcCxu4iJZBBGtG0MtsNsgJ40anumbrelladeiMac
这里我只是简单演示了一下退出服务端发送的请求,如果我们CAS系统接入很多客户端,具体客户端在不同的地址,我们就可以配置自己相应的logoutUrl,然后在被动退出时在POST监听地址中销毁掉session即可。
代码实例:Chapter10