cas4.0服务端集群

 
 

cas服务端集群,相信网上资料也蛮多的,无非就是session共享,ticket共享


关于session共享 上一篇tomcat redis session manager已经给出了具体的解决方案,这里主要说一下ticket共享问题
首先定义自己的ticketRegistory 如下


然后修改ticketRegistory.xml 文件 屏蔽掉

 <!--  <bean id="ticketRegistry" class="org.jasig.cas.ticket.registry.DefaultTicketRegistry" /> -->
	
	<!-- Quartz
	TICKET REGISTRY CLEANER -->
	<!-- <bean id="ticketRegistryCleaner" class="org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner"
		p:ticketRegistry-ref="ticketRegistry"
		p:logoutManager-ref="logoutManager" />
	
	<bean id="jobDetailTicketRegistryCleaner" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
		p:targetObject-ref="ticketRegistryCleaner"
		p:targetMethod="clean" />
	
	<bean id="triggerJobDetailTicketRegistryCleaner" class="org.springframework.scheduling.quartz.SimpleTriggerBean"
		p:jobDetail-ref="jobDetailTicketRegistryCleaner"
		p:startDelay="20000"
		p:repeatInterval="5000000" /> -->

添加
  <bean id="ticketRegistry" class="com.cn.instai.cas.registry.RedisTicketRegistry" 
  	p:redisManager-ref="redisManager"
  	p:stMaxFreeTime="${st.timeToKillInSeconds}"
  	p:tgtMaxFreeTime="${tgt.timeToKillInSeconds}"
  />

${st.timeToKillInSeconds} 与  <span style="font-family: Arial, Helvetica, sans-serif;">${tgt.timeToKillInSeconds} 根据具体情况赋值</span>

到此 ticket的共享完成 

但是测试发现 单点登出虽然ticket是会清楚  但没法单点登出成功  调试发现  以这种方式共享ticket时候  logout时候没有向请求系统发送logoutRequest请求

4.0采用的是logout-webflow 流程结构,查看logout-webflow.xml
<action-state id="terminateSession">
    <evaluate expression="terminateSessionAction.terminate(flowRequestContext)" />
    <transition to="doLogout" />
  </action-state>
找到开始节点 注意 主要登出业务处理地方  刚开始被我忽略了,一直跟着logoutAction源码   最后发现原来处理都是在terminateSession

cas-server.xml中找到 id为terminateSessionAction的bean   类为org.jasig.cas.web.flow.TerminateSessionAction
<evaluate expression="terminateSessionAction.terminate(flowRequestContext)" />这一句 其实就是调用 TerminateSessionAction 的terminate方法
代码如下

发现 centralAuthenticationService.destroyTicketGrantingTicket 发现原来是调用了 centralAuthenticationService的销毁 tgt票据的方法
查看该方法
查看 logoutManager的performLogout方法
发现  services = ticket.getServices(); 如果采用默认的ticketRegistry 可以获取到所有service 而如果采用RedisTicketRegistry获取到的services为空的

这里 总算是找到导致没法单点登出的原因了 两种redisTicketRegistry里面保存的TGT票据 不包含 客户端登录过的servie信息  

于是查看 ServiceValidateController 开始我以为是在认证st票据的时候 存储了对应的servie信息 结果好像没发现

后来看到 C entralAuthenticationServiceImpl中的grantServiceTicket方法

//TGT票据对授权ST票据
 final ServiceTicket serviceTicket = ticketGrantingTicket.grantServiceTicket(generatedServiceTicketId, service,
                this.serviceTicketExpirationPolicy, credentials != null);
        this.serviceTicketRegistry.addTicket(serviceTicket);

TGT票据grantServiceTicket方法

断点比较两种票据存储方式的区别 发现当使用redisTicketRegistry是 这里对TGT票据services的修改 不会更新到redis中
于是自定义了一个 centralAuthenticationService的实现类 在TGT票据授权ST票据后 对TGT票据做了一下刷新
即在ticketGrantingTicket.grantServiceTicket后面增加了一行代码
this.serviceTicketRegistry.addTicket(ticketGrantingTicket);
这里由于redis key相同会覆盖 实际效果和更新一样

到此cas服务端的集群完成
      
希望大神们能给出更好的解决思路

你可能感兴趣的:(redis,集群)