zoukankan      html  css  js  c++  java
  • Shiro Session集群共享存入Redis中SimpleSession的transient 属性不能序列化

    Session存入Redis中SimpleSession的transient属性不能序列化

    最开始实现共享Session的方法,是基于这篇博客实现的SpringBoot+redis 实现shiro集群共享session 。但是原有项目有redis的一些配置,就没用文章里的redis序列化方式,踩了一个大坑。

    问题描述

    通过 redis 缓存 shiro 的 session,取值的时候 session id内容为 null。

    java.lang.IllegalArgumentException: The org.apache.shiro.session.mgt.DelegatingSession implementation requires that the SessionKey argument returns a non-null sessionId to support the Session.getId() invocations.
    

    断点调试发现redis在存入SimpleSession时都是有值的,只是获取出来后一些属性是为null的。 What? 小朋友你是不是有很多的问号????

    原因分析

    因为 shiro 的 Session 是一个 SimpleSession 类,其中属性用 transient 修饰,即不能被序列化。

    RedisTemplate 默认使用JdkSerializationRedisSerializer,这个序列化模式会将value序列化成字节码,这样缓存shiro的session就没有什么问题。 但是一般都会用Fastjson、Jackson2Json来指定redis的序列化方式,这样的方式就会导致数据存取不一致问题。

    public class SimpleSession implements ValidatingSession, Serializable {
        private static final long serialVersionUID = -7125642695178165650L;
        private static final transient Logger log = LoggerFactory.getLogger(SimpleSession.class);
        protected static final long MILLIS_PER_SECOND = 1000L;
        protected static final long MILLIS_PER_MINUTE = 60000L;
        protected static final long MILLIS_PER_HOUR = 3600000L;
        static int bitIndexCounter = 0;
        private static final int ID_BIT_MASK;
        private static final int START_TIMESTAMP_BIT_MASK;
        private static final int STOP_TIMESTAMP_BIT_MASK;
        private static final int LAST_ACCESS_TIME_BIT_MASK;
        private static final int TIMEOUT_BIT_MASK;
        private static final int EXPIRED_BIT_MASK;
        private static final int HOST_BIT_MASK;
        private static final int ATTRIBUTES_BIT_MASK;
        private transient Serializable id;
        private transient Date startTimestamp;
        private transient Date stopTimestamp;
        private transient Date lastAccessTime;
        private transient long timeout;
        private transient boolean expired;
        private transient String host;
        private transient Map<Object, Object> attributes;
    

    解决方案

    • 方案1. 修改序列化工具类
    • 方案2.继承SimpleSession并重写,让相关的字段可以被序列化(不被transient修饰)

    我最终结果是放弃了自己写RedisManager、SessionDAO,因为项目框架这边redis序列化相关的不好改,使用crazycake写的开源插件

    详见 : 2020-04-01-SpringBoot+Shiro基于Redis实现共享Session

    参考文章:

  • 相关阅读:
    jsp_Scriptlet
    jsp_注释
    Http状态码详解
    Tomcat服务器的安装和配置
    【BZOJ 1018】线段树 **
    【BZOJ 2054】 2054: 疯狂的馒头 (并查集特技)
    【BZOJ 1969】 1969: [Ahoi2005]LANE 航线规划 (树链剖分+线段树)
    【BZOJ 1880】 [Sdoi2009]Elaxia的路线 (最短路树)
    【UOJ 79】 一般图最大匹配 (✿带花树开花)
    【UOJ 34】 多项式乘法 (FFT)
  • 原文地址:https://www.cnblogs.com/cnsyear/p/12633178.html
Copyright © 2011-2022 走看看