cas的session存储及实现共享的原理:
cas在HashMapBackedSessionMappingStorage存session所以后面可以根据自己的tic,结合cookie反向生成session放到新的web服务器中
集群思想:cas通过redis覆写可以实现多节点cas的集群(都是用redis存储session,不再使用HashMapBackedSessionMappingStorage这个内部的map存)
cas是开源的登录认证方案,可以实现多个web应用的单点登录。
随着用户量的增加,web应用需要部署多个实例,要实现不同应用、多实例的共享session,需要先了解cas的logout机制。简单的说,web应用在接入cas的时候需要继承cas-client-core,这个模块完成的事情如下:
- 拦截到web应用的请求,验证登录状态,若未登录则跳转到登录页
- 登录成功,web应用的tomcat存储session,cas-server保存TGT信息,cas-client-core保存ST和session的对应关系
- 登出时由cas-server返回ST信息,cas-client-core根据ST删除自己存储在内存的ST和session信息
要实现共享session,就需要解决以下两个问题:
tomcat默认的session是存在在内存的,因此要实现共享就需要实现session存储到数据库,考虑到用户操作需要频繁读取session,因此redis很适合用来实现session统一存储。
tomcat-redis-session-manager是开源的tomcat共享session插件,这里需要注意要下载比较新的master版本,我当时是下了稳定版本tomcat-redis-session-manager-1.2-tomcat-7-java-7,结果一直在死循环,阅读源码才修改了其中的bug,后面发现master已经修复bug。
我用的插件版本如下:
- commons-pool-1.6.jar
- jedis-2.0.0.jar
- 修改bug后的tomcat-redis-session-manager-1.2-tomcat-7-java-7.jar
然后按照官网的说明,只需要在tomcat的context.xml简单加上配置就ok
cas-client-core共享ST和session
cas-client-core利用HashMapBackedSessionMappingStorage实现了ST和session的内存存储,因此很简单,我们只需要实现使用redis存储ST和session的缓存,替换该接口即可。
这里在序列化存储的时候碰到头疼的问题,StandardSessionFacade没有实现序列化,如果改动StandardSessionFacade需要重新编译catalina的jar包,比较麻烦所以没有选择该方案。
那怎么办呢?在集成了tomcat-redis-session-manager插件后,tomcat使用的session最终实例其实还是RedisSession,这个必然实现了序列化接口,因此我们只需要存储这个实例即可。问题来了,StandardSessionFacade的变量session为private,真是处处坑。。只能用java反射来获取了。以下是redis保存ST和session的源码:
- @Override
- public void addSessionById(String mappingId, HttpSession session) {
- String STKey = getKey(mappingId);
- StandardSessionFacade standardSessionFacade = (StandardSessionFacade) session;
- RedisSession redisSession = null;
- try {
- redisSession = (RedisSession) getValue(standardSessionFacade, "session");
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (NoSuchFieldException e) {
- e.printStackTrace();
- }
- if (null == redisSession) {
- log.error("get redisSession fail");
- return;
- }
- sessionRedisTemplate.opsForValue().set(STKey, jdkSerializer.serialize(redisSession));
- String sessionKey = getKey(session.getId());
- stringRedisTemplate.opsForValue().set(sessionKey, STKey);
- log.debug("cas-client add session, mappingId:" + mappingId + " sessionId:" + session.getId());
- }
- public void destroySession(final HttpServletRequest request) {
- final String logoutMessage = CommonUtils.safeGetParameter(request, this.logoutParameterName);
- if (log.isTraceEnabled()) {
- log.trace("Logout request:\n" + logoutMessage);
- }
- final String token = XmlUtils.getTextForElement(logoutMessage, "SessionIndex");
- if (CommonUtils.isNotBlank(token)) {
- final HttpSession session = this.sessionMappingStorage.removeSessionByMappingId(token);
- if (session != null) {
- String sessionID = session.getId();
- if (log.isDebugEnabled()) {
- log.debug("Invalidating session [" + sessionID + "] for token [" + token + "]");
- }
- try {
- session.invalidate();
- } catch (final IllegalStateException e) {
- log.debug("Error invalidating session.", e);
- }
- }
- }
- }
- @Override
- public HttpSession removeSessionByMappingId(String mappingId) {
- String STKey = getKey(mappingId);
- log.debug("cas-client remove session, STKey:" + STKey);
- RedisSession session = null;
- byte[] value = (byte[]) sessionRedisTemplate.opsForValue().get(STKey);
- session = (RedisSession) jdkSerializer.deserialize(value);
- if (null == session) {
- log.error("session is null");
- return null;
- }
- removeBySessionById(session.getId());
- sessionRedisTemplate.delete(session.getId());
- log.debug("delete session:" + session.getId());
- return session;
- }
- @Override
- public void removeBySessionById(String sessionId) {
- log.debug("Attempting to remove Session=[" + sessionId + "]");
- String sessionKey = getKey(sessionId);
- String st = stringRedisTemplate.opsForValue().get(sessionKey);
- if (log.isDebugEnabled()) {
- if (st != null) {
- log.debug("Found mapping for session. Session Removed.");
- } else {
- log.debug("No mapping for session found. Ignoring.");
- }
- }
- stringRedisTemplate.delete(sessionKey);
- sessionRedisTemplate.delete(st);
- }
相关推荐
CASClient 集群环境的 Session 问题及解决方案 本文将详细介绍 CASClient 集群环境中的 Session 问题及解决方案。CASClient 是一种开源的单点登录系统,能够提供统一的登录和注销机制。但是在集群环境中应用 CAS...
PHP的memcache扩展提供了一个解决方案,它是一个高性能的分布式内存对象缓存系统,常被用来作为session存储后端。通过配置php.ini文件,可以将session的存储机制从默认的文件系统改为memcache服务器集群。 具体实现...
CAS系统会将用户的认证信息存储在Cookie或Session中,以便在用户访问不同的应用系统时,自动进行认证。 二、CAS单点登录系统的优点 CAS单点登录系统的优点主要包括: * 减少用户在不同系统中登录耗费的时间,减少...
在Web开发中,Session是服务器用来跟踪用户状态的一种机制,它是服务器端存储用户信息的方式。在用户登录后,服务器会创建一个Session,并将用户的登录信息(如用户ID、用户名等)存储在这个Session对象中,然后将...
- 会话管理:通过将用户的会话信息序列化并存储在Redis中,可以实现跨服务器的会话共享,提高系统的可扩展性。 - 票据管理:TGT是CAS SSO机制的核心,用于生成后续的服务票据(Service Ticket)。将TGT存储在Redis...
这样,所有的Web应用都会使用同一个session存储,达到共享目的。例如,可以创建一个全局的`GlobalNamingResources`,并在各个应用中引用它。 5. **使用分布式session**:如果在集群环境中,可以使用如Memcached、...
2. **统一Session存储**: - **数据库存储**:文中提供的`Session`类示例展示了如何将Session数据存储在MySQL数据库中。这种方法适用于多台服务器或跨域情况,因为数据存储在集中式位置。但需要注意,频繁的Session...
Spring Boot 整合 Redis 实现 Shiro 的分布式 Session 共享 Shiro 是一个优秀的 Java 安全框架,提供了强大的身份验证、授权和会话管理功能。然而,在分布式架构中,Shiro 的会话管理机制需要进行特殊处理,以便...
3. **设置Ticket共享**:推荐使用Redis作为Ticket的存储介质,确保Ticket数据能在所有CAS服务器间共享。 4. **部署Nginx负载均衡器**:配置Nginx作为前端负载均衡器,负责将外部请求分发至后端的CAS服务器集群。 #...
- `test1`接收到来自CAS服务器的重定向请求后,检查TGC中存储的TGT是否与其自身session中存储的TGT一致。如果不一致,则`test1`会向CAS服务器发送ST进行验证。 - CAS服务器验证ST的有效性后,确认用户身份无误,并将...
1. **集中式Session存储**:所有应用的Session信息都存储在一个集中的存储系统(如Redis或Memcached)中,而不是本地Session。 2. **Session ID匹配**:用户登录后,CAS会生成一个全局的Session ID,并分配给所有...
CAS(Central Authentication Service)是实现SSO的一种开源协议,它提供了一个中心认证服务器和一组标准化的接口,使得不同的应用系统能够共享同一个认证服务。 在SSO系统中,Cookie是实现跨域身份验证的关键。当...
同时,CI的Session机制还支持数据库存储,使得在多服务器环境下更容易共享session数据,提高了系统的可扩展性。 总的来说,CI框架的Session组件通过自定义的实现,提供了一套强大而灵活的session管理方案,结合了...
在JSP中,实现SSO的关键在于正确管理和共享Cookie与Session。Cookie是客户端存储的信息,而Session是服务器端存储的信息。登录成功后,服务器会在用户的浏览器上设置一个全局Cookie,并在Session中保存相应的用户...
它通过将认证信息集中存储在服务端(即CAS服务器),来实现子系统间的登录状态共享。一旦用户通过CAS服务器认证,他或她就可以访问其他配置了CAS认证的子系统,而无需再次登录。 知识点二:Django CAS解决方案的...
将SpringBoot、Shiro和Redis整合,主要目的是利用Shiro进行用户认证和授权,而Redis作为Session的共享存储,解决分布式环境下的会话一致性问题。以下是整合步骤: 1. **引入依赖**:在SpringBoot的pom.xml文件中...
2. **Session管理**:在X-uni-session中,session服务端负责存储和管理用户登录状态。每个用户登录时,会在服务器上创建一个session对象,其中包含用户的唯一标识和其他相关信息。通过session,服务端可以追踪用户的...
通过解压并研究"singleLogin"文件,你可以更深入地理解如何在实际项目中整合SSO功能,包括SSM框架的使用、Spring Security的配置、以及Redis作为session共享的实现细节。这将有助于提升你的SSO实施能力,同时对...