cas client集群单点登出解决方案总结

来源:互联网 发布:网络硬盘 编辑:程序博客网 时间:2024/06/07 20:39

cas client提供了单点出功能SLO.但对于cas client 在集群环境下的单点登出的情况深入了解的甚少,因为默认情况下它不是很灵,也就是说有时能登出,有时登不出的情况。最近一段时间,在新公司进行技术预演,这个问题又遇到了,所以对于其深入了解一下。

部署说明

对于project_A部署两个tomcat1,tomcat2端口分别为8080,9090,nginx 运行部口80,ip统一为192.168.31.100.cas server部署为单机192.168.31.101:8080;

  • cas-client.jar 版本号为3.4.1(github上cas client有好多年没有更新了);

  • cas server 版本号4.1.10,可参见 https://github.com/zhuzhong/cas-web.git

nginx反向代理tomcat1,tomcat2,为了能够顺利登陆,下面三项需要选项一项去作(如果你不知道原因,我也不会告诉你):

  • nginx路由规则 ip_hash

  • nginx session sticky

  • tomcat session集群或session共享;

在这里我选择ip_hash,最终nginx的up_stream部分:

    upstream pro_a {            ip_hash;            server 192.168.31.101:8080;            server 192.168.31.101:9090;        }

单点登出问题

用户通过浏览器,访问 192.168.31.100/proj_a/index 进行访问,能够顺利登陆成功。但是在单点登出出现问题,有时无法登出。

单点登出问题原因分析

cas client在用户登陆时,在HashMapBackedSessionMappingStorage(在jvm中)存储一份关于token与当前httpSession的对应关系。当用户访问proj_A通过ip_hash 路由到tomcat1,则此时httpsession在tomcat1创建,也在tomcat1的jvm存储。

当用户发送登出请求,cas server 默认使用的是 BACK_CHANNEL的消息通知登出请求(logoutrequest),经nginx ip_hash 路由之后,则有可能至tomcat2,然后通过token无法获取相应的httpsession 无法进行销毁,所以无法单点登出;

解决方案第一版本

修改cas client 的单点退出 code.进行二次组播发出登出请求。具体描述如下:
对于cas server 发送登出请求至nginx,经ip_hash至tomcat2,这种情形,二次处理。即当没有找到相应的httpsession时,则对于proj_a的所有部署节点都进行二次登出请求,在这里即对于
http://192.168.31.100:8080/proj_a/index,http://192.168.31.100:9090/proj_a/index 发出登出请求。
在节点 tomcat1,上则会找到相应的httpsession然后将其无效掉,则登出任务完成。

但这里有一个遗留问题,即前端登陆页面无法进行二次重定向回到登陆页面,它会仍然停留在发出登出请求的页面,给用户以假象没有登出。所以这个不是完美的解决方案。
对于这个版本,对应的修改代码,参见https://github.com/zhuzhong/cas-client-logout-extend.git 分支名logout-broadcast.

解决方案第二版本

将nginx的ip_hash, 更换成tomcat session cluster,以求出现好的结果,但是问题依旧,即也不是完美的解决方案。在作之前即有结论与解决方案第一版本结果一样。之所以试试,就是因为技术人员就这样,凡事都要试试才知道。

解决方案第三版本

这个方案是偶然间发现的。在进行cas client的单点登出代码修改的时候,发现在有个方法SingleSignOutHandler.isFrontChannelLogoutRequest始终没有被调用过,而只调用SingleSignOutHandle.isBackChannelLogoutRequest。当初也没在意,因为登出的逻辑就是这样,只是使用了不同的方式。但是在
SingleSignOutHandler.process方法中,对于isFrontChannelLogoutRequest多了一次重定向。所以果断将登出方式改为FRONT_CHANNEl,然后测试,ok,没有问题,能够达到预设的目的。登出方式的修改在cas server中src/main/resources/services/HTTPSandIMAPS-10000001.json的 “logoutType” : “BACK_CHANNEL”, 修改为 “logoutType” : “FRONT_CHANNEL”即可。

总结

经过几个版本,几天的折磨困扰的这个问题,终于算是有了个结果。之所以没有很快解决这个问题主要的原因是对于cas 的登出逻辑不是很熟悉。之前都只关心登陆,没有太关心过登出。对于登出,程序员都有绝招,让用户关浏览器。所以对于这个没有进行太深入的研究,理解不深。后续如果有时间,对于cas的登出作一个详尽的分析。

原创粉丝点击