shiro session设置了过期时间不起作用、无效;

背景知识

虽然本文主要是讲述shiro设置session过期时间无效问题,但是shiro的sesssion由sessionmanager管理,所以这里有必要介绍一下sessionmanager,这样有助于理解。shiro常用的sessionmanager有ServletContainerSessionManagerDefaultWebSessionManager

  • servlet container session
    设置为ServletContainerSessionManager时,session的操作由servlet容器(tomcat、jetty)负责,简单来说shiro只起桥接作用,这时的session过期时间,在web.xml中的sessiontimeout中指定;

    
      
      30
    
    
  • native session
    设置为 DefaultWebSessionManager时,session是native session,也就是本地session,由shiro管理session(创建、更新、销毁),跟servlet容器没有关系。这种情况时,session的过期时间在shiro配置文件中指定。

bug再现

通常我们都会选择shiro自己管理session,shiro配置配置如下


	
		
		
	
	
		
		
	
  
  

这里过期时间指定为1800000毫秒=30分钟*60秒*1000毫秒,也就是30分钟。
EnterpriseCacheSessionDAO的父类CachingSessionDAO,定义了缓存session的缓存块名字

public abstract class CachingSessionDAO extends AbstractSessionDAO implements CacheManagerAware {

    /**
     * The default active sessions cache name, equal to {@code shiro-activeSessionCache}.
     */
    public static final String ACTIVE_SESSION_CACHE_NAME = "shiro-activeSessionCache";
    }

所以ehcache的通常会有shiro-activeSessionCache块,配置如下


这样配置有2个错误。

  • timeToIdleSeconds配置为2分钟,如果2分钟内没有交互,session就会从ehcache中删除
  • 受内存限制,session过多应该被写到磁盘上,但是overflowToDisk=false,无法写到磁盘,被删除

以上两种错误,都是ehcache自作主张导致session未过期而删除,未通知session调度器。正确的做法是只有session调度器 有权删除,ehcache不能自行删除,这就要求ehcache中session的空闲时间为永久、如果内存不够就写到磁盘,如果要求重启jvm session不丢失,还需要diskPersistent=true。顺便说一下,session调度器默认是每隔1小时,执行一次。
正确的配置应该为


eternal="true"  
timeToIdleSeconds="0" 
timeToLiveSeconds="0" 
overflowToDisk="true" 
diskPersistent="true" 
/>

其实在shiro-ehcache.jar中,有个ehcache.xml(对应java中的net.sf.ehcache.config.CacheConfiguration),里边的注释也明确说明了这个问题

 
    

总结

  • 设置session过期时间不起作用,是因为ehcache自行删除导致;
  • redis/ehcache与session的运作机制搞懂了。缓存只用来存储session,不能自行删除,session调度器负责check session有效性,如果过期,则明确指示redis/ehcache删除session。

参考

shiro session management

你可能感兴趣的:(shiro,ehcache)