`

cas 集群环境代码开发

    博客分类:
  • cas
阅读更多
注:转载自 http://blog.csdn.net/roadmap001/article/details/8686301

单点登录(SSO)是复杂应用系统的基本需求,Yale CAS是目前常用的开源解决方案。CAS认证中心,基于其特殊作用,自然会成为整个应用系统的核心,所有应用系统的认证工作,都将请求到CAS来完成。因此CAS服务器是整个应用的关键节点,CAS发生故障,所有系统都将陷入瘫痪。同时,CAS的负载能力要足够强,能够承担所有的认证请求响应。利用负载均衡和集群技术,不仅能克服CAS单点故障,同时将认证请求分布到多台CAS服务器上,有效减轻单台CAS服务器的请求压力。下面将基于CAS 3.4.5来讨论下CAS集群。

CAS的工作原理,主要是基于票据(Ticket)来实现的(参见 CAS基本原理)。CAS票据,存储在TicketRegistry中,因此要想实现CAS Cluster, 必须要多台CAS之间共享所有的Ticket,采用统一的TicketRegistry,可以达到此目的。  缺省的CAS实现中,TicketRegistry在内存中实现,不同的CAS服务器有自己单独的TicketRegistry,因此是不支持分布式集群的。但CAS提供了支持TicketRegistry分布式的接口org.jasig.cas.ticket.registry.AbstractDistributedTicketRegistry,我们可以实现这个接口实现多台CAS服务器TicketRegistry共享,从而实现CAS集群。

同时,较新版本CAS使用SpringWebFlow作为认证流程,而webflow需要使用session存储流程相关信息,因此实现CAS集群,我们还得需要让不同服务器的session进行共享。

我们采用内存数据库Redis来实现TicketRegistry,让多个CAS服务器共用同一个TicketRegistry。同样方法,我们让session也存储在Redis中,达到共享session的目的。下面就说说如何用Redis来实现TicketRegistry,我们使用Java调用接口Jedis来操作Redis,代码如下:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;

import org.jasig.cas.ticket.Ticket;
import org.jasig.cas.ticket.TicketGrantingTicket;
import org.jasig.cas.ticket.registry.AbstractDistributedTicketRegistry;


import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;


/*
 *  TicketRegistry using Redis, to solve CAS Cluster.
 *  
 *  @author ZL
 * 
 */

public class RedisTicketRegistry extends AbstractDistributedTicketRegistry {

	
	private static int redisDatabaseNum;
	private static String hosts;
	private static int port;
         private static int st_time;  //ST最大空闲时间
          private static int tgt_time; //TGT最大空闲时间
    
	private static JedisPool cachePool;
	
	static {
	
		redisDatabaseNum = PropertiesConfigUtil.getPropertyInt("redis_database_num");
		hosts = PropertiesConfigUtil.getProperty("hosts");
		port = PropertiesConfigUtil.getPropertyInt("port");
		st_time = PropertiesConfigUtil.getPropertyInt("st_time");
		tgt_time = PropertiesConfigUtil.getPropertyInt("tgt_time");
		cachePool = new JedisPool(new JedisPoolConfig(), hosts, port);
		
	}
	
	public void addTicket(Ticket ticket) {
			
		Jedis jedis = cachePool.getResource();
		jedis.select(redisDatabaseNum);
		
                  int seconds = 0;

                  String key = ticket.getId() ;
		
		if(ticket instanceof TicketGrantingTicket){
			//key = ((TicketGrantingTicket)ticket).getAuthentication().getPrincipal().getId();
			seconds = tgt_time/1000;
		}else{
			seconds = st_time/1000;
		}
  
		
	    ByteArrayOutputStream bos = new ByteArrayOutputStream();
	    ObjectOutputStream oos = null;
	    try{
		    oos = new ObjectOutputStream(bos);
		    oos.writeObject(ticket);
		   
	    }catch(Exception e){
	    	log.error("adding ticket to redis error.");
	    }finally{
	    	try{ 
	    		if(null!=oos) oos.close();
	    	}catch(Exception e){
	    		log.error("oos closing error when adding ticket to redis.");
	    	}
	    }
	    jedis.set(key.getBytes(), bos.toByteArray());
		jedis.expire(key.getBytes(), seconds);
		
		cachePool.returnResource(jedis);
		
	}
	
    public Ticket getTicket(final String ticketId) {
        return getProxiedTicketInstance(getRawTicket(ticketId));
    }
	
	
    private Ticket getRawTicket(final String ticketId) {
		
    	if(null == ticketId) return null;
    	
    	Jedis jedis = cachePool.getResource();
		jedis.select(redisDatabaseNum);
		
		Ticket ticket = null;
        
        ByteArrayInputStream bais = new ByteArrayInputStream(jedis.get(ticketId.getBytes()));
		ObjectInputStream ois = null;
		
		try{
			ois = new ObjectInputStream(bais);
			ticket = (Ticket)ois.readObject(); 
		}catch(Exception e){
			log.error("getting ticket to redis error.");
		}finally{
			try{
				if(null!=ois)  ois.close();
			}catch(Exception e){
				log.error("ois closing error when getting ticket to redis.");
			}
		}
        
		cachePool.returnResource(jedis);
		
		return ticket;
    }
   
    

    public boolean deleteTicket(final String ticketId) {
        
        if (ticketId == null) {
            return false;
        }
        
        
		Jedis jedis = cachePool.getResource();
		jedis.select(redisDatabaseNum);
			
		jedis.del(ticketId.getBytes());
	    
        cachePool.returnResource(jedis);
        
        return true;        
    }
 
	public Collection<Ticket> getTickets() {
		
		throw new UnsupportedOperationException("GetTickets not supported.");

	}

    protected boolean needsCallback() {
        return false;
    }
    
    protected void updateTicket(final Ticket ticket) {
        addTicket(ticket);
    }
 
}



同时,我们在ticketRegistry.xml配置文件中,将TicketRegistry实现类指定为上述实现。即修改下面的class值

    <!-- Ticket Registry -->
 	<bean id="ticketRegistry" class="org.jasig.cas.util.RedisTicketRegistry" />
	
<!-- 	<bean id="ticketRegistry" class="org.jasig.cas.ticket.registry.DefaultTicketRegistry" />
 -->	


因为使用了Redis的expire功能,注释掉如下代码:
	<!-- TICKET REGISTRY CLEANER -->
<!-- 	<bean id="ticketRegistryCleaner" class="org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner"
		p:ticketRegistry-ref="ticketRegistry" />
	
	<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" /> -->


通过上述实现TicketRegistry,多台CAS服务器就可以共用同一个TicketRegistry。对于如何共享session,我们可以采用现成的第三方工具tomcat-redis-session-manager直接集成即可。对于前端web服务器(如nginx),做好负载均衡配置,将认证请求分布转发给后面多台CAS,实现负载均衡和容错目的。
分享到:
评论

相关推荐

    SSO CAS Server 二次开发说明文档

    为了便于进行二次开发,推荐使用Maven overlays特性来构建开发环境。这样可以利用最新版本的资源文件覆盖现有WAR包中的文件,无需手动导入整个`cas-server-webapp`模块的源代码。通过这种方式,只需按照源代码中的...

    基于CAS集群的单点失效问题解决方案

    - **CAS集群介绍**:CAS(Central Authentication Service)是由耶鲁大学开发的一种开放源代码的单点登录系统,它支持多种认证协议,并且能够与多种应用系统进行无缝集成。尽管CAS本身已经非常成熟且可靠,但它最初...

    cas-overlay-template-6.4 服务端代码

    10.CAS-redisCluster集群存储ticket(相应redis必须配置成cluster集群) 11.CAS-加密存储ticket 12.CAS-实习动态验证码 13.CAS-实习自定义登录 14.CAS-实现自定义返回用户登录信息 15.CAS-页面缓存记住我 ----------...

    cas4.2.4、cas4.0war包

    CAS(Central Authentication Service)是一种广泛使用的开放源代码身份验证框架,它允许用户通过单个登录(Single Sign-On,SSO)访问多个应用系统。在您提供的信息中,我们有两个版本的CAS服务器WAR包:cas-server...

    JavaEE求职简历-姓名-JAVA开发工程师.doc

    - 参与项目需求分析,模块划分,搭建开发环境,设计数据库表。 - 负责员工管理、公告管理、部门管理、职位管理的代码开发。 - 技术栈:Spring+SpringMvc+MyBatis+DBunit+EasyMock+Json。 - 物理架构:MySQL+...

    JAVA上百实例源码以及开源项目源代码

    Tcp服务端与客户端的JAVA实例源代码 2个目标文件 摘要:Java源码,文件操作,TCP,服务器 Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多...

    jeefuseMDA用户开发手册1

    它管理对象的生命周期,负责对象间的依赖关系,使得代码更解耦,易于测试和维护。通过配置文件或注解,Spring可以自动装配bean,实现灵活的依赖注入。 3. Web MVC框架: Struts2 和 Spring MVC 是两种广泛使用的...

    XXX-JAVA开发工程师-2年经验简历模板

    - **Eclipse/IDEA**:Eclipse和IntelliJ IDEA是常用的Java集成开发环境(IDE),它们提供了丰富的功能,如代码编辑、调试、构建等。 - **Maven**:Maven是一个项目管理和综合工具,可以帮助开发者自动化项目的构建...

    JavaEE求职简历-姓名-JAVA开发工程师.docx

    7. **单点登录(SSO)**:用户登录采用了CAS系统,实现了跨多个应用的单点登录,简化了用户认证流程。 8. **搜索引擎**:使用Solr进行全文检索,提升了商品搜索的效率和准确性。 9. **前端技术**:熟悉HTML、CSS、...

    PyPI 官网下载 | ftw.casauth-1.4.1.tar.gz

    PyPI(Python Package Index)是Python开发者的重要资源库,它提供了大量的开源软件包和模块,使得开发人员能够轻松地分享和使用他人的代码。在本次讨论中,我们将关注的是`ftw.casauth-1.4.1.tar.gz`,这是一个在...

    CAS_project

    部署可能涉及将CAS服务器设置为高可用性集群,以防止单点故障。 10. **持续集成/持续部署(CI/CD)**:在现代开发流程中,CI/CD工具(如Jenkins、GitLab CI/CD等)可能用于自动化构建、测试和部署过程,确保代码质量...

    etcd二进制包,解压即可直接伤脑筋

    etcd是CoreOS开发的一个分布式键值存储系统,它被设计为高可用的,并且用于在分布式计算环境中协调服务和配置。etcd以其简洁、稳定和高性能的特点在云计算和微服务架构中广泛应用,例如作为Kubernetes等容器编排系统...

    Piflow是一个基于分布式计算框架Spark开发的大数据流水线系统

    文件“cas-bigdatalab-piflow-3e06a22”很可能是一个Piflow的特定版本或示例代码仓库,用户可以下载这个压缩包来研究、部署或扩展Piflow的功能。在这个版本中,可能包含了源代码、文档、示例流水线配置以及测试用例...

    黑马品优购项目

    单点登录:cas 权限管理:SpringSecurity, 跨域:cros 支付:微信扫描 短信验证:阿里大于 密码加密:BCrypt 富文本:KindEditor 事务:声明式事务 任务调度:spring task 所有的技术,都可能涉及到为什么用?怎么...

    微服务网关gateway集成security

    在现代企业级应用开发中,微服务架构已经成为主流,它将大型系统拆分成小型、独立的服务,每个服务都能独立部署和扩展。而Spring Cloud Gateway作为一款强大的微服务网关,承担着路由、过滤器等功能,它能有效地为...

    SSM+ehcache-Jar包

    Ehcache不仅可以作为本地缓存,还可以在分布式环境中使用,支持集群和 terracotta 集群解决方案。 压缩包中的具体文件说明如下: - **ehcache-web-2.0.4.jar**:这是Ehcache的Web扩展,提供了与Web应用集成的功能...

    全新JAVAEE大神完美就业实战课程 超150G巨制课程轻松实战JAVAEE课程 就业部分.txt

    day01_电商介绍--互联网术语-SOA-分布式-集群介绍-环境配置-框架搭建 day02_Dubbo介绍_dubbo框架整合_商品列表查询实现_分页_逆向工程 day03_Git day04_门户网站介绍&商城首页搭建&内容系统创建&CMS实现 day05_...

    【白雪红叶】JAVA学习技术栈梳理思维导图.xmind

    集群 分片 Key-hash 异步 一致性hash 消峰 分库分表 锁 悲观锁 乐观锁 行级锁 分布式锁 分区排队 一致性 一致性算法 paxos zab nwr raft gossip 柔性事务(TCC) 一致性原理 CAP BASE ...

Global site tag (gtag.js) - Google Analytics