基于Redis的CAS服务端集群
2017-01-09 15:33
369 查看
为了保证生产环境CAS(Central Authentication Service)认证服务的高可用,防止出现单点故障,我们需要对CAS Server进行集群部署。
CAS的Ticket默认是以Map的方式存储在JVM内存中的,多个tomcat之间无法共享,因此我们可以使用MemCached或者Redis来存储Ticket。MemCached的方式官方已经提供了解决方案,我们这里使用的是Redis,具体实现可以参考CAS的模块:cas-server-integration-memcached。
1、pom.xml文件中加入依赖:
2、参考:org.jasig.cas.ticket.registry.MemCacheTicketRegistry,重写Ticket注册类。
3、修改“ticketRegistry.xml”,先删除文件中原有的bean定义,包括ticketRegistry、ticketRegistryCleaner、jobDetailTicketRegistryCleaner和triggerJobDetailTicketRegistryCleaner,然后添加下面的代码片段:
4、配置Tomcat集群,实现Session共享,参考:https://github.com/jcoleman/tomcat-redis-session-manager。
到此,基于Redis的CAS Server集群配置已经完成。
“CAS单点登录初使用”
“CAS单点登录与Shiro的集成”
“CAS单点登录密码加盐的认证”
“CAS+Shiro实现单点退出”
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 deleteTicket(String ticketId) { if (ticketId == null) { return false; } final Ticket ticket = getTicket(ticketId); if (ticket == null) { return false; } logger.debug("Deleting ticket {}", ticketId); try { this.redisTemplate.delete(ticketId); } catch (final Exception e) { logger.error("Failed deleting {}", ticketId, e); } return false; } @Override protected void updateTicket(Ticket ticket) { logger.debug("Updating ticket {}", ticket); try { if(this.redisTemplate.hasKey(ticket.getId())) { this.redisTemplate.opsForValue().set(ticket.getId(), ticket, getTimeout(ticket), TimeUnit.SECONDS); } } catch (final Exception e) { logger.error("Failed updating {}", ticket, e); } } @Override public Collection<Ticket> getTickets() { throw new UnsupportedOperationException("GetTickets not supported."); } @Override protected boolean needsCallback() { return true; } @Override public void destroy() throws Exception { } /** * Gets the timeout value for the ticket. * * @param t the t * @return the timeout */ private int getTimeout(final Ticket t) { if (t instanceof TicketGrantingTicket) { return this.tgtTimeout; } else if (t instanceof ServiceTicket) { return this.stTimeout; } throw new IllegalArgumentException("Invalid ticket type"); } }
3、修改“ticketRegistry.xml”,先删除文件中原有的bean定义,包括ticketRegistry、ticketRegistryCleaner、jobDetailTicketRegistryCleaner和triggerJobDetailTicketRegistryCleaner,然后添加下面的代码片段:
<bean id="ticketRegistry" class="com.***.cas.ticket.registry.RedisTicketRegistry"> <constructor-arg index="0" ref="redisTemplate" /> <constructor-arg index="1" value="1800" /> <constructor-arg index="2" value="10" /> </bean> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="200" /> <property name="testOnBorrow" value="true" /> </bean> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${redis.host}"/> <property name="port" value="6379"/> <property name="poolConfig" ref="jedisPoolConfig"/> </bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory"/> </bean>
4、配置Tomcat集群,实现Session共享,参考:https://github.com/jcoleman/tomcat-redis-session-manager。
到此,基于Redis的CAS Server集群配置已经完成。
“CAS单点登录初使用”
“CAS单点登录与Shiro的集成”
“CAS单点登录密码加盐的认证”
“CAS+Shiro实现单点退出”
相关文章推荐
- 基于Redis的CAS集群
- redis基于sentinel的集群服务端、客户端示例
- 基于redis的cas集群配置(转)
- 基于Redis的CAS集群
- 基于redis的cas集群配置
- 基于Redis的CAS集群
- 基于Redis Sentinel的Redis集群(主从&amp;Sharding)高可用方案
- 基于Redis Sentinel的Redis集群(主从&Sharding)高可用方案
- 基于Redis Sentinel的Redis集群(主从&Sharding)高可用方案
- 基于Redis Sentinel的Redis集群(主从&Sharding)高可用方案
- 基于Redis Sentinel的Redis集群(主从&Sharding)高可用方案
- Tomcat7集群共享Session 基于redis进行统一管理
- 基于keepalived、redis sentinel的高可用redis集群【修改版】
- 基于redis集群实现的分布式锁,可用于秒杀商品的库存数量管理,有测试代码(何志雄)
- Redis集群研究和实践(基于redis 3.0.5)(不错)
- 基于Redis Sentinel的Redis集群(主从&Sharding)高可用方案
- Redis学习笔记(五) 基于Redis 3.0的集群
- 基于keepalived、redis sentinel的多实例redis集群【2】---realserver配置
- 基于keepalived、redis sentinel的多实例redis集群【1】---路由以及哨兵配置
- redis的安装配置及其基于sentinel的redis集群高可用方案