Apache Shiro SessionManager

SessionManager是在应用程序中为所有Subject提供Session的管理,包括创建,删除,失效及验证等。同其的核心组件一样,SessionManager也是一个由SecurityManager维护的顶级组件。

Shiro中默认提供了一个SessionManager的实现DefaultSessionManagerDefaultSessionManager提供一个应用程序所需的所有企业级会话管理。可以在任何应用程序中使用。

如果想自定义一个SessionManager,可在Shiro.ini中配置。例如:

[main]

sessionManager=com.foo.my.SessionManagerImplementation

securityManager.sessionManager=$sessionManager

在系统中SessionManager可以通过JavaBean风格的getter/setter方法获取或设置(getSessionManager()/setSessionManager())。

下面介绍默认的SessionManager包含的一些额配置项:

SessionTimeout

默认是30分钟。也就是说,如果任何Session创建后闲置(未被使用,未被更新)的时间超过了30分钟,那么该Session就被认为是过期的,且不允许再被使用。

你可以通过globalSessionTimeout属性来为所有的会话定义默认的超时时间。例如,如果你想超时时间是一个小时而不是30分钟:

[main]

#3,600,000milliseconds=1hour

securityManager.sessionManager.globalSessionTimeout=3600000

Per-SessionTimeout

上面的globalSessionTimeout值默认是为所有新建的Session使用的。你可以在每一个会话的基础上控制超时时间通过设置单独的会话超时时间值。与上面的globalSessionTimeout一样,该值以毫秒(不是秒)为时间单位。

SessionListeners

Shiro支持SessionListener概念来允许你对发生的重要会话作出反应。你可以实现SessionListener接口(或扩展易用的SessionListenerAdapter)来与相应的会话操作作出反应。

由于默认的SessionManagersessionListeners属性是一个集合,你可以对SessionManager配置一个或多个listener实现,就像其他在shiro.ini中的集合一样:

[main]

aSessionListener=com.foo.my.SessionListener

anotherSessionListener=com.foo.my.OtherSessionListener

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

当任何会话事件发生时,SessionListeners都会被通知——不仅仅是对一个特定的会话。

SessionStorage

每当一个会话被创建或更新时,它的数据需要持久化到一个存储位置以便它能够被稍后的应用程序访问。同样地,当一个会话失效且不再被使用时,它需要从存储中删除以便会话数据存储空间不会被耗尽。SessionManager实现了这些Create/Read/Update/Delete(CRUD)操作做为内部组件,同时,通过SessionDAO反映了数据访问对象(DAO)设计模式。

SessionDAO的作用是你能够通过该接口来与你想要的任何数据存储进行通信。这意味着你的会话数据可以驻留在内存中,文件系统,关系数据库或NoSQL的数据存储,或其他任何你需要的位置。

你可以将任何SessionDAO实现作为一个属性配置在默认的SessionManager实例上。例如,在shiro.ini中:

[main]

sessionDAO=com.foo.my.SessionDAO

securityManager.sessionManager.sessionDAO=$sessionDAO

Shiro已经有一些很好的SessionDAO实现,你可以立即使用或实现你需要的子类。

EHCacheSessionDAO

EHCache默认是没有启用的,但如果你不打算实现你自己的SessionDAO,那么强烈地建议你为ShiroSessionManagerment启用EHCache支持。EHCacheSessionDAO将会在内存中保存会话,并支持若内存不足时可溢出到磁盘。这对确保你在运行时不会随机地“丢失”会话是非常好的。

为所有Shiro的缓存需要使用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=$cacheManager,为所有Shiro的需要配置了一个CacheManager。该CacheManager实例会自动地直接传送到SessionDAO(通过EnterpriseCacheSessionDAO实现CacheManagerAware接口的性质)。

然后,当SessionManager要求EnterpriseCacheSessionDAO去持久化一个Session时,它使用一个EHCache支持的Cache实现去存储Session数据。

CustomSessionIDs

Shiro的SessionDAO在创建一个新的会话时使用一个内置的SessionIdGenerator组件来产生一个新的SessionID。该ID生成后,被指派给新近创建的Session实例,然后该Session通过SessionDAO被保存下来。

默认的SessionIdGenerator是一个JavaUuidSessionIdGenerator,它能产生基于JavaUUIDsStringIDs。该实现能够支持所有的生产环境。

如果它不符合你的需要,你可以实现SessionIdGenerator接口并在ShiroSessionDAO实例上配置该实现。例如,在shiro.ini中:

[main]

...

sessionIdGenerator=com.my.session.SessionIdGenerator

securityManager.sessionManager.sessionDAO.sessionIdGenerator=$sessionIdGenerator

SessionValidation&Scheduling

Sessions必须被验证,这样任何无效(过期或停止)的会话能够从会话数据存储中删除。这保证了数据存储不会由于不能再次使用的会话而导致写入超时。

由于性能上的原因,仅仅在Sessions被访问(也就是subject.getSession())时验证它们是否停止或过期。这意味着,如果没有额外的定期验证,Sessionorphans(孤儿)将会开始填充会话数据存储。

会话孤儿,如果它们没有定期清除,将会填充会话数据存储(这是很糟糕的)。因此,为了防止丢放孤儿,SessionManager实现支持SessionValidationScheduler的概念。SessionValidationScheduler负责定期地验证会话以确保它们是否需要清理。

DefaultSessionValidationScheduler

默认可用的SessionValidationScheduler在所有环境中都是ExecutorServiceSessionValidationScheduler,它使用JDKScheduledExecutorService来控制验证频率。

默认地,该实现每小时执行一次验证。你可以通过指定一个新的ExecutorServiceSessionValidationScheduler实例并指定不同的间隔(以毫秒为单位)改变速率来更改验证频率:

[main]

sessionValidationScheduler=org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler

#Defaultis3,600,000millis=1hour:

sessionValidationScheduler.interval=3600000

securityManager.sessionManager.sessionValidationScheduler=$sessionValidationScheduler

CustomSessionValidationScheduler

如果你希望提供一个自定义的SessionValidationScheduler实现,你可以指定它作为默认的SessionManager实例的一个属性。例如,在shiro.ini中:

[main]

sessionValidationScheduler=com.foo.my.SessionValidationScheduler

securityManager.sessionManager.sessionValidationScheduler=$sessionValidationScheduler

DisablingSessionValidation

在某些情况下,你可能希望禁用会话验证项,由于你建立了一个超出了Shiro控制的进程来为你执行验证。例如,也许你正在使用一个企业的Cache并依赖于缓存的TimeToLive设置来自动地去除旧的会话。或者也许你已经制定了一个计划任务来自动清理一个自定义的数据存储。在这些情况下你可以关掉sessionvalidationscheduling

[main]

securityManager.sessionManager.sessionValidationSchedulerEnabled=false

当会话从会话数据存储取回数据时它仍然会被验证,但这会禁用掉Shiro的定期验证。

EnableSessionValidationsomewhere

如果你关闭了Shirosessionvalidationscheduler,你必须通过其他的机制(计划任务等)来执行定期的会话验证。这是保证会话孤儿不会填充数据存储的唯一方法。

InvalidSessionDeletion

正如我们上面所说的,进行定期的会话验证主要目的是为了删除任何无效的(过期或停止)会话来确保它们不会填充会话数据存储。

默认地,某些应用程序可能不希望Shiro自动地删除会话。例如,如果一个应用程序已经提供了一个SessionDAO备份数据存储查询,也许是应用程序团队希望旧的或无效的会话在一定的时间内可用。这将允许团队对数据存储运行查询来判断,例如,在上周某个用户创建了多少个会话,或一个用户会话的持续时间,或与之类似报告类型的查询。

在这些情形中,你可以关闭invalidsessiondeletion项。例如,在shiro.ini中:

[main]

securityManager.sessionManager.deletInvalidSessions=false

请注意!如果你关闭了它,你得为确保你的会话数据存储不耗尽它的空间复杂。你必须自己从你的数据存储中删除无效的会话!

还要注意,即使你阻止了Shiro删除无效的会话,你仍然应该使用某种会话验证方式——要没通过Shiro的现有验证机制,要么通过一个你自己提供的自定义的机制(见上述的"DisablingSessionValidation"获取更多)。验证机制将会更新你的会话记录以反映无效的状态(例如,什么时候它是无效的,它最后一次被访问是什么时候,等等),即使你在其他的一些时间将手动删除它们。

如果你配置Shiro来让它不会删除无效的会话,你得为确保你的会话数据存储不会耗尽它的空间负责。你必须亲自从你的数据存储删除无效的会话!

另外请注意,禁用会话删除并不等同于禁用sessionvalidationschedule(会话验证调度)。你应该总是使用一个会话验证调度机制——无论是Shiro直接支持或者是你自己的。


Shiro 中,SessionManager 负责管理用户的会话信息,其主要职责包括创建、获取、删除和管理会话等。下面是一个简单的 Shiro SessionManager 的配置示例: ```xml <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <!-- session过期时间,单位:毫秒 --> <property name="globalSessionTimeout" value="1800000" /> <!-- 是否开启URL地址栏中的SessionID重写 --> <property name="sessionIdUrlRewritingEnabled" value="false" /> <!-- 是否开启删除无效的session对象 --> <property name="deleteInvalidSessions" value="true" /> <!-- 是否开启定时调度器检测失效的session对象 --> <property name="sessionValidationSchedulerEnabled" value="true" /> <!-- 定时清理失效session的时间间隔,单位:毫秒;默认1小时 --> <property name="sessionValidationInterval" value="3600000" /> <!-- 会话DAO --> <property name="sessionDAO" ref="redisSessionDAO" /> </bean> ``` 其中,`DefaultWebSessionManager` 是 Shiro 默认提供的 Web 环境下的 SessionManager 实现类,我们可以通过配置它的属性来实现相关功能。具体的属性含义如下: - `globalSessionTimeout`:会话超时时间,单位为毫秒,默认为30分钟。 - `sessionIdUrlRewritingEnabled`:是否在URL地址栏中重写Session ID,默认为false,建议不开启,因为这会让URL泄漏了Session ID,存在安全风险。 - `deleteInvalidSessions`:是否开启删除无效Session对象,默认为true,表示当Session超时或者被踢出时自动删除相应的Session对象。 - `sessionValidationSchedulerEnabled`:是否开启定时调度器检测失效的Session对象,默认为true,表示在应用启动时会启动一个定时任务,定期检测失效的Session并删除它们。 - `sessionValidationInterval`:定时清理失效Session的时间间隔,单位为毫秒,默认为1小时。 - `sessionDAO`:指定会话DAO,即会话的存储方式。这里我们使用 Redis 作为会话存储方式,所以指定了 `redisSessionDAO`。 需要注意的是,如果要使用 Redis 作为会话存储方式,还需要配置相应的 `redisSessionDAO`。具体的配置可以参考下面的示例: ```xml <bean id="redisSessionDAO" class="org.crazycake.shiro.RedisSessionDAO"> <!-- 配置RedisManager --> <property name="redisManager" ref="redisManager" /> <!-- session在Redis中的过期时间,单位是秒 --> <property name="expire" value="1800" /> </bean> <bean id="redisManager" class="org.crazycake.shiro.RedisManager"> <!-- Redis服务器地址,格式为:host:port --> <property name="host" value="127.0.0.1:6379" /> <!-- Redis服务器连接超时时间,单位为毫秒,默认为2000ms --> <property name="timeout" value="2000" /> <!-- Redis服务器密码,如果没有设置可以不填 --> <property name="password" value="your_password" /> <!-- Redis数据库编号,默认为0 --> <property name="database" value="0" /> </bean> ``` 其中,`RedisSessionDAO` 是一个实现了 Shiro `SessionDAO` 接口的 Redis Session 存储类。`RedisManager` 则是一个 Redis 连接管理类,用于管理与 Redis 服务器的连接。需要注意的是,上面的 `redisSessionDAO` 和 `redisManager` 需要通过 Spring 容器进行管理,所以需要在 Spring 配置文件中进行相应的配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值