做sso时候,集成cas的rememberMe功能时,报错:java.io.NotSerializableException: java.util.HashMap$KeySet。
首先cas集成rememberMe的具体配置可以可以参照【http://blog.csdn.net/jadyer/article/details/47110353】进行配置,
cas集成redis的配置:
1. 配置redis相关bean
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="1024" /> <property name="maxIdle" value="200" /> <property name="maxWaitMillis" value="1000" /> <property name="testOnBorrow" value="true" /> <property name="testOnReturn" value="true" /> </bean> <!-- redis的连接池pool,不是必选项:timeout/password --> <bean id="jedisPool" class="redis.clients.jedis.JedisPool"> <constructor-arg index="0" ref="jedisPoolConfig" /> <constructor-arg index="1" value="127.0.0.1" /> <constructor-arg index="2" value="6379" type="int" /> <constructor-arg index="3" value="20" type="int" /> </bean>
2.在ticketRegistry.xml将Ticket Registry托管到redis 管理,
<!--Ticket Registry托管到redis 管理, --> <bean id="ticketRegistry" class="com.xxx.xxx.ticketRegistry.RegisTicketRegistry" p:tgtTime="3000000" p:stTime="300000" p:dbnum="8" p:pool-ref="jedisPool" p:logoutManager-ref="logoutManager" />
即可。
3.RedisTicketRegistry中的addTicket(),执行到oos.writeObject(ticket); 抛出异常 java.io.NotSerializableException: java.util.HashMap$KeySet
public void addTicket( final Ticket ticket) { Jedis jedis = pool.getResource(); jedis.select(Integer.valueOf(dbnum)); int seconds = 0; String key = ticket.getId(); if (ticket instanceof TicketGrantingTicket) { seconds = Integer.valueOf(tgtTime) / 1000; } else { seconds = Integer.valueOf(stTime) / 1000; } ByteArrayOutputStream bos = null; ObjectOutputStream oos = null; try { bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); oos.writeObject(ticket); } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != oos) oos.close(); } catch (Exception e) { e.printStackTrace(); } } byte[] ticketBytes = bos.toByteArray(); jedis.set(key.getBytes(), ticketBytes); jedis.expire(key.getBytes(), seconds); pool.returnResource(jedis); }
4.在执行RedisTicketRegistry.addTicket()方法oos.writeObject(ticket);时候会报错,
java.io.NotSerializableException: java.util.HashMap$KeySet。
最终定位错误原因:是在cas+rememberMe配置时候,(具体配置参照【http://blog.csdn.net/jadyer/article/details/47110353】),
deployerConfigContext.xml,authenticationManager中增加了配置:
<!-- 针对RememberMe需增加的属性配置 --> <property name="authenticationMetaDataPopulators"> <list> <bean class="org.jasig.cas.authentication.SuccessfulHandlerMetaDataPopulator"/> <bean class="org.jasig.cas.authentication.principal.RememberMeAuthenticationMetaDataPopulator"/> </list> </property>
最终错误定位到SuccessfulHandlerMetaDataPopulator.populateAttributes()方法中
public class SuccessfulHandlerMetaDataPopulator implements AuthenticationMetaDataPopulator { /** Attribute name containing collection of handler names that successfully authenticated credential. */ public static final String SUCCESSFUL_AUTHENTICATION_HANDLERS = "successfulAuthenticationHandlers"; @Override public void populateAttributes(final AuthenticationBuilder builder, final Credential credential) { builder.addAttribute(SUCCESSFUL_AUTHENTICATION_HANDLERS, builder.getSuccesses().keySet()); } }
根本原因是jdk中Set没有实现Serializable不支持序列化,如下test实例:
public class SerializableTest { private static Map<String,Object> infoMap = null; private static ByteArrayOutputStream bos = null; private static ObjectOutputStream oos = null; @BeforeClass public static void setUp() throws IOException{ infoMap = new HashMap<String,Object>(); infoMap.put("name", "张三"); infoMap.put("age", 18); infoMap.put("birthdate", new Date()); bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); } @Test public void testSerializableSet() throws IOException{ /** * Set 继承Collection > Iterable 不支持序列化 * 抛出异常 java.io.NotSerializableException: java.util.HashMap$KeySet */ Set<String> set = infoMap.keySet(); oos.writeObject(set); } @Test @SuppressWarnings({ "rawtypes", "unchecked" }) public void testSerializableHashSet() throws IOException{ /** * HashSet实现了java.io.Serializable接口,支持序列化 */ HashSet<String> hashSet = new HashSet(infoMap.keySet()); oos.writeObject(hashSet); } }
最终解决方案:
//builder.addAttribute(SUCCESSFUL_AUTHENTICATION_HANDLERS, builder.getSuccesses().keySet()); builder.addAttribute(SUCCESSFUL_AUTHENTICATION_HANDLERS, new HashSet(builder.getSuccesses().keySet()));
相关推荐
# 下载 redis-3.2.1.gem然后本地安装 sudo gem install -l ./redis-3.2.1.gem port 6379 daemonize yes #bind自己的ip bind 192.168.129.101 protected-mode no #启用集群 cluster-enabled yes cluster-config-file ...
标签:springframework、data、spring、redis、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和...
在Linux系统中安装Redis是一个常见的任务,特别是在搭建分布式缓存或数据库系统时。Redis是一款开源、高性能、基于键值对的数据存储系统,广泛应用于数据缓存、消息队列和数据库等多个场景。本教程将详细讲解如何在...
5. **客户端连接**:客户端连接到集群时,需要使用支持Redis集群的客户端库,如Jedis(Java)、StackExchange.Redis(C#)等,它们会处理槽的路由和重定向。 6. **监控与维护**:定期检查集群状态,使用`CLUSTER ...
标签:netty、codec、redis、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心...
1. 客户端连接:可以使用内置的`redis-cli`客户端,或第三方工具如`Jedis`(Java)、`StackExchange.Redis`(C#)等。 2. 数据操作:通过命令行或编程接口进行数据的读写操作,如`SET key value`、`GET key`、`LPUSH...
Redis 是一个高性能的键值数据库,常用于缓存和数据持久化。它的高效性得益于其内存存储特性,以及丰富的数据结构支持,如字符串、哈希、列表、集合和有序集合。Redis-3.2.11.tar.gz 文件是Redis 3.2.11版本的源代码...
解决报错_org.springframework.data.redis.serializer.SerializationException_ Could not write_read JSON
赠送jar包:spring-session-data-redis-2.0.4....标签:springframework、session、spring、data、redis、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文
redis安装 1: 下载redis-5.0.4.tar.gz 2: 解压源码并进入目录 tar zxvf redis-5.0.4.tar.gz cd redis-5.0.4 3: 不用configure 4: 直接make (如果是32位机器 make 32bit) 查看linux机器是32位还是64位的方法:...
标签:codec、redis、netty、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心...
java.lang.NoSuchMethodError: redis.clients.jedis.ScanResult.getStringCursor()Ljava/lang/String; at org.crazycake.shiro.WorkAloneRedisManager.keys(WorkAloneRedisManager.java:149) at org.crazycake....
标签:springframework、data、spring、redis、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明...
下载redis(http://redis.io/) 2.上传到linux 3.在 usr/local下新建文件夹 redis mkdir /usr/local/redis 4.将root下的redis移动到 /usr/local/redis 然后解压 mv redis-3.0.7.tar.gz /usr/local/redis/ cd /...
1. **src**:包含Redis服务器的C语言源代码,如`redis-server`(主进程), `redis-cli`(命令行客户端), `redis-benchmark`(性能测试工具)以及`redis-check-dump`和`redis-check-aof`(数据检查工具)等。...
Socket.IO Redis发射器 @socket.io/redis-emitter软件包使您可以轻松地与另一个Node.js进程(服务器端)中的一组Socket.IO服务器进行通信。 发射器还提供其他编程语言版本: Java: : Python: : PHP: : Golang...
Redis 是一个高性能的键值对数据库,常被用于构建数据缓存、消息队列和数据库。在Linux系统中,Redis的安装通常涉及下载源码、编译和配置等步骤。这里我们将详细介绍如何处理"最新版linux redis-6.2.1.tar.gz"这个...
redis 配置集群必备
Redis是一款高性能的键值对数据库,常用于缓存、消息队列等场景。该压缩包“redis-3.0.5.tar.gz”是为Linux系统准备的安装包,包含了Redis服务器的所有源代码及相关文件,版本号为3.0.5。在Linux环境下,通过这个包...
标签:codec、redis、netty、jar包、java、中英对照文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请...