为了保证生产环境CAS(Central Authentication Service)认证服务的高可用,防止出现单点故障,我们需要对CAS Server进行集群部署。
CAS的Ticket默认是以Map的方式存储在JVM内存中的,多个tomcat之间无法共享,因此我们可以使用MemCached或者Redis来存储Ticket。MemCached的方式官方已经提供了解决方案,我们这里使用的是Redis,具体实现可以参考CAS的模块:cas-server-integration-memcached。
1、pom.xml文件中加入依赖:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.0.RELEASE</version>
</dependency>
2、参考:org.jasig.cas.ticket.registry.MemCacheTicketRegistry,重写Ticket注册类。
package com.***.cas.ticket.registry;
import org.jasig.cas.ticket.ServiceTicket;
import org.jasig.cas.ticket.Ticket;
import org.jasig.cas.ticket.TicketGrantingTicket;
import org.jasig.cas.ticket.registry.AbstractDistributedTicketRegistry;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.data.redis.core.RedisTemplate;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
public final class RedisTicketRegistry extends AbstractDistributedTicketRegistry implements DisposableBean {
/** Memcached client. */
@NotNull
private final RedisTemplate<String, Object> redisTemplate;
/**
* TGT cache entry timeout in seconds.
*/
@Min(0)
private final int tgtTimeout;
/**
* ST cache entry timeout in seconds.
*/
@Min(0)
private final int stTimeout;
public RedisTicketRegistry(RedisTemplate<String, Object> redisTemplate, int tgtTimeout, int stTimeout) {
this.redisTemplate = redisTemplate;
this.tgtTimeout = tgtTimeout;
this.stTimeout = stTimeout;
}
@Override
public void addTicket(Ticket ticket) {
logger.debug("Adding ticket {}", ticket);
try {
this.redisTemplate.opsForValue().set(ticket.getId(),ticket, getTimeout(ticket), TimeUnit.SECONDS);
} catch (Exception e) {
logger.error("Failed adding {}", ticket, e);
}
}
@Override
public Ticket getTicket(String ticketId) {
try {
final Ticket t = (Ticket) this.redisTemplate.opsForValue().get(ticketId);
if (t != null) {
return getProxiedTicketInstance(t);
}
} catch (final Exception e) {
logger.error("Failed fetching {} ", ticketId, e);
}
return null;
}
@Override
public boolean