记录grails3项目中使用spring security cas插件遇到的单点登出问题。
依据文档进行cas相关配置。测试发现cas客户端退出后,其他cas客户端依然是登录状态,本文记录解决这个问题的过程。
-
首先想到的是,客户端1退出的时候是否没有通知到cas服务端。
验证:在自定义的TGTDestoryEventListener类中加上断点。
结果:进入断点,cas接收到客户端的退出申请,进行了销票操作。
-
既然cas服务已经进行了销票操作,那是不是没有把退出的消息通知到登录的客户端呢,继续验证。
验证:在DefaultLogoutManager的performLogout中加入断点,查看是否得到logoutReuqest。
结果:得到logoutRequests,所以cas已经成功发出通知。
-
cas服务已经发出了通知,那么问题就在cas客户端了。
查看spring security cas源码,是由SingleSignOutFilter接收cas服务端发出的注销session请求的,具体操作由SingleSignOutHandler完成。
在SingleSignOutHandler中,当登录成功的时候会将ST和session一块存入sessionMappingStorage中,当收到退出申请的时候,从sessionMappingStorage中找到对应session,进行invalidate操作。
验证:是否进行session.invalidate()
结果:抛出异常session already invalidate
多次观察发现,当进行到session.invalidate()时,session的isValid属性一直是false,所以会抛出异常。正常情况下isValid应该是true,猜测是在某一步骤将isValid置为了false。
-- 至此思路断了,没有定位到是哪里的操作。 -
时隔多天再次尝试解决这个问题。
在controller中获取sessionId,发现和sessionMappingStorage存储的是不一样的,通过F12网络观察cookies的变化,发现在登录成功之后,cookie中的sessionId发生了变化,所以猜测应该是登录成功后造成的。
查阅了spring security core插件的文档,发现了其中的一段说明,意思是登录后是否将现有会话的会话属性复制到新会话,默认是true,如下图
尝试将该功能关闭,进行验证,成功退出。。。