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

參考文章:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM