Shiro学习笔记(6)-Session

前言

Shiro本身提供完整的Session管理(无论是在什么环境),通过Session,可以自定义一些属性让shiro进行管理(例如可以存储密码进行定期的保存)。接下来,本篇文章会着重讲解在Shiro中如何使用Session以及Session的一些特性。

使用Session

Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
session.setAttribute("key", "value");

和之前的代码类似,获取Session也是通过Subject对象。并且getSession()默认是调用的getSession(true)。当参数为true是,存在Session则直接返回,如果不存在则创建一个新的;当传递false时,则不创建Session。

SessionManager

从名字就可以看出,SessionManager是用来管理所有Subject的Session的,隶属于SecurityManager管理。因此可以通过配置化(shiro.ini)的形式自定义SessionManger实现。如下所示

[main]
...
sessionManager = com.mamba.bootstrap.SessionManagerImplementation
securityManager.sessionManager = $sessionManager

需要注意的是我们通常会使用Shiro自带的SessionManager。

Session timeout

Session默认也有过期时间,默认30分钟后时失效,可以通过配置的方式来设置全局失效时间

[main]
...
# 3,600,000 milliseconds = 1 hour
securityManager.sessionManager.globalSessionTimeout = 3600000

如果想要设置单个session的过期时间,则可以调用单独的setTimeout方法进行设置

Session Listeners

Shiro也支持针对Session的监听事件,可以在session启动、停止、过期等状态做出响应。针对SessionListeners的配置如下所示:

[main]
...
aSessionListener = com.mamba.sessionListener1
anotherSessionListener = com.mamba.sessionListener2

securityManager.sessionManager.sessionListeners = $aSessionListener, $anotherSessionListener.

需要注意配置的监听器是针对所有session进行配置的

Session存储

  • SeesionDao:用来保存Session中的数据,可以通过实现SeesionDao决定Session数据存放的方式.关于SessionDao的配置如下:
[main]
...
sessionDAO = com.mamba.SessionDAO
securityManager.sessionManager.sessionDAO = $sessionDAO

需要注意的是,如果是在Web环境,不会默认使用SessionDao。需要进行如下声明来使用shiro自带的WebSessionManager

sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager

EHCache SessionDAO

  • Shiro支持EhCache作为Session的存储方式,EHCache可以实现内存存储的同时溢出到磁盘来进行数据存储。如果想要开启则需要进行如下配置:
[main]

sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
securityManager.sessionManager.sessionDAO = $sessionDAO

cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
securityManager.cacheManager = $cacheManager

可以看见需要通过securityManager.cacheManager来指定使用哪种缓存存储方式。

  • 配置EhCache
    shiro提供了 EhCache的默认配置ehcache.xml,内容如下:
<cache name="shiro-activeSessionCache"
       maxElementsInMemory="10000"
       overflowToDisk="true"
       eternal="true"
       timeToLiveSeconds="0"
       timeToIdleSeconds="0"
       diskPersistent="true"
       diskExpiryThreadIntervalSeconds="600"/>

shiro也支持用户自定义缓存参数,但是需要注意的是overflowToDisk和eternal这两个参数必须要存在。并且需要指定自定义配置文件的路径

shiroCacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
shiroCacheManager.cacheManagerConfigFile = classpath:conf/ehcache-shiro.xml

并且在具体使用缓存参数的时候需要指定name

sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionDAO.activeSessionsCacheName = shiro-activeSessionCache

自定义Session Id

首先,Shiro默认提供了一个Session Id 生成器,使用的是JavaUuidSessionIdGenerator。如果想使用自己定义的生成器,则需要通过实现SessionIdGenerator接口,并且具体的配置如下:

[main]
...
sessionIdGenerator = com.my.session.SessionIdGenerator
securityManager.sessionManager.sessionDAO.sessionIdGenerator = $sessionIdGenerator

Session定期检查

如果没有Session的定期检查,会出现一种情况:例如用户是非正常退出登录,shiro并不知道需要关闭当前的session,久而久之session数据会被填充满。为了防止这种情况的发生,Shiro默认提供了ExecutorServiceSessionValidationScheduler来对Session定期进行检查,默认是一个小时。如果想要自定义时间,需要进行如下配置:

[main]
...
sessionValidationScheduler = org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler
# Default is 3,600,000 millis = 1 hour:
sessionValidationScheduler.interval = 3600000

securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler

自定义SessionValidationScheduler

如果不想使用shiro提供的默认SessionValidationScheduler,我们还可以进行指定创建,需要实现SessionValidationScheduler接口,具体的配置如下:

[main]
...
sessionValidationScheduler = com.foo.my.SessionValidationScheduler
securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler

禁用Session定期检查

如果默认不想使用这个功能(可能你自己通过外部的工具或者其他方式解决了这个问题),可以通过如下配置来禁用:

[main]
...
securityManager.sessionManager.sessionValidationSchedulerEnabled = false

注意这种方式只是停止了定期检查Session的数据,但是在每次查询的时候还是进行验证,如果想要彻底禁止Session检查(可能有需要查过期Session或者其他数据的需求),那么需要进行如下配置

[main]
...
securityManager.sessionManager.deleteInvalidSessions = false

需要注意的是,如果禁止删除Session。你需要自己手动进行验证,防止存储空间用光。一般情况下,都应该允许自动地Session检查

Session集群

Shiro支持Session集群的方式来存储session的数据,具体的集群方式可以指定决定(EhCache、redis等都可以实现集群)。关于如何在Shiro中触发集群的配置主要有两种方式、具体如下所示:

#This implementation would use your preferred distributed caching product's APIs:
activeSessionsCache = my.org.apache.shiro.cache.CacheImplementation

sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionDAO.activeSessionsCache = $activeSessionsCache

securityManager.sessionManager.sessionDAO = $sessionDAO

这种方式通过配置SessionDao的activeSessionsCache来实现,还有一种方式如下:

cacheManager = my.org.apache.shiro.cache.CacheManagerImplementation
 
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
 
sessionDAO.activeSessionsCacheName = shiro-activeSessionsCache
 
securityManager.sessionManager.sessionDAO = $sessionDAO
 
securityManager.cacheManager = $cacheManager

这种方式通过配置securityManager.cacheManager的来实现。

注意,关于集体如何使用存储需要自己实现Cache接口接口

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章