公司应用线很多,使用CAS4.1.10作为单点登录中心,自己实现了单点登出功能,但是发现CAS在发生账号复用的时候会产生单点登出失败的问题。
名词解释:TGT:TicketGrantingTicket;ST:ServiceTicket
表现为:A在自己电脑上使用001帐号登录了数个应用,此后B也在自己的电脑上使用001帐号登录了数个应用;此后A的电脑上的应用将出现无法单点登出的问题。原因是登出时将注销ST并销毁TGT,TGT销毁时将发送注销通知给所有关联的ST实现单点登出。账号复用后,CAS在颁发ST的时候将会出现ST和TGT的关联关系被覆盖的现象,导致:A电脑上的注销操作注销ST,但ST关联关系已经被覆盖至B电脑的TGT,结果销毁TGT没有成功,没有响应单点登出。
另一种问题表现形式是:账号复用后,A电脑上的登出操作将导致B电脑上的TGT同时被销毁,同一账号的不同TGT同时触发注销程序,注销通知发生回环(类似麦克风的回音),最终导致A、B两台电脑均无法正常使用。直至A、B双方都关闭浏览器终端,终止通知回环。
解决方案:账号复用导致的问题原因在于TGT和ST的关联关系,如果想要允许复用的话,需要自己建立一个关联方式取代CAS原有的关联即可(也许需要改动的地方不少,没细看)。我们的方案是禁止账号复用,即需要实现单用户登录,所以需要通过修改实现A电脑登录之后再去B电脑登录,A电脑即被踢出。
实现方案:
经过跟踪排查,管理登录时TGT与ST颁发的代码内容均在
org.jasig.cas.CentralAuthenticationServiceImpl
这个类当中。
而管理和记录TGT和ST并记录关联的内容均在
org.jasig.cas.ticket.registry.DefaultTicketRegistry
这个类当中。不要怂,就是刚,抄起键盘就是干!
研究了一圈,发现能添加TGT的地方有不止一处,为了以后扩展方便(少找麻烦),不去动它们,那就只能在它们汇总的地方做文章了。
org.jasig.cas.ticket.registry.DefaultTicketRegistry
import org.jasig.cas.ticket.ServiceTicket;
import org.jasig.cas.ticket.Ticket;
import org.jasig.cas.ticket.TicketG