Shiro————会话管理

引言

本篇博客翻译自Shiro 官方网站的 Session Manager 手册。

网页地址:http://shiro.apache.org/session-management.html

Shiro 会话管理支持的特性

  • 基于POJO/J2SE(IoC容器友好的)- Shiro 中的所有东西都是基于接口的,而且是以 POJO作为实现。因此你可以很容易地配置所有兼容 JavaBean 的会话组件,如 JSON,YAML, Spring XML,或者类似的机制。你也可以很容易的扩展Shiro 的组件,或在必要情况下完全自定义 session 管理的功能。
  • 简单的自定义 Session 存储 - 因为 Shiro 的 Session 对象是基于 POJO的,因此 Session 数据可以存储在任意数量的数据源中。因此,你可以自定义你的应用 session 存储的位置,例如,文件系统、内存、分布式的网络缓存、关系型数据库,或者是专有数据存储区。
  • 不依赖容器的集群! - Shiro 的session 可以被任何缓存产品集群管理,如Ehcache + Terracotta, Coherence, GigaSpaces 等等。这意味着你只需要配置一次 Session 集群,不论你的应用会部署到哪种容器,你的 session 都将以同样的方式聚集。不需要针对特定容器的配置。
  • Heterogeneous Client Access - Unlike EJB or Web sessions, Shiro sessions can be ‘shared’ across various client technologies. For example, a desktop application could ‘see’ and ‘share’ the same physical session used by the same user in a web application. We are unaware of any framework other than Shiro that can support this.
  • 事件监听 - 事件监听允许你监听 session 的生命周期。你可以监听它们并对这些事件作出自定义的操作,例如,当某个用户的 session 过期时更新数据库的记录。
  • 主机地址保留 - Shiro Session 会保留发起主机的 IP 地址。因此,你可以据此来确定用户的位置并作出相应的反应(通常在IP 关联关系确定的 内网环境比较有用)
  • 支持用户无操作/过期 - 由于用户无操作而导致 Session 超时是人们期望看到的,但 session 可以通过 touch()方法保持“活跃”。这在富互联网应用环境非常有用,用户可能一直在使用桌面应用,而并没有定期与服务端产生交互,但 server 端的 session 不应该因此而过期。
  • Web 使用透明(无障碍感) - Shiro 对 web 的支持 完全实现了和支持了 Servlet 2.5 对 Session 的规范(HttpSession 接口和与它相关的所有API)。也就是说你可以在已创建的 Web 应用中使用 Shiro 的Session ,而且不需要更改任何代码。
  • 可以使用在 SSO上 - 因为 Shiro 的Session 是基于 POJO 的,它们可以被存储到任意的数据源上,而且,如果需要的话可以在多个应用间进行共享。它还可以提供简单的登录体验,因为共享会话可以保留身份验证状态(单点登录)。

使用 Session

和Shiro 中几乎所有的东西一样,要获得 Session 对象,你需要和当前执行的 用户 产生某种作用。

Subject currentUser = SecurityUtils.getSubject();

Session session = currentUser.getSession();
session.setAttribute( "someKey", someValue);

currentUser.getSession() 方法默认调用了 currentUser.getSession(true)。

对于那些熟悉 HttpServletRequest API 的人,Subject.getSession(boolean create) 方法在功能上和HttpServletRequest.getSession(boolean create) 方法完全一致。

  • 如果 Subject 已经有了一个 Session ,布尔类型的参数将被忽略,而直接返回 session 对象。
  • 如果 Subject 还没有一个Session ,且参数为 true,就会创建一个 Session 对象并返回。
  • 如果 Subject 还没有一个 Session ,且参数为 false, 就不会创建 Session ,并且返回 null。

注意:getSession方法的调用在所有应用中都适用,即便不是web 应用。

subject.getSession(false) 在开发框架代码确定不需要创建新的 Session 时,可以获得良好的效果。

一旦你获得了一个 Subject 的 Session ,你可以用它来做许多事情,例如设置和取出属性,设置它的 timeout,等等。参考Session JavaDoc 查看更多信息。

会话管理器

SessionManager,顾名思义,管理应用中所有 subject 的 session  - 创建、删除、无活动过期 等等。和其他 Shiro 中的架构组件一样,SessionManager 对象也是一个被SecurityManager 持有的顶级组件。

默认的 SecurityManager 实现默认使用开箱即用的 DefaultSessionManager。DefaultSessionManager可以提供所有企业级 session 管理特性,如 会话过期、清理等等,且同样适用于所有类型的应用。

Web 应用

Web 应用可以使用不同的 SessionManager实现类。请参考 Web 文档查看 web特定的 Session 管理信息。

和其他被 SecurityManager 管理的组件一样, SessionManager 可以通过JavaBean的形式通过 get、set 方法组装到所有 Shiro 默认的 SecurityManager 实现对象上(getSessionManager()/setSessionManager())。或者例如下面,使用 shiro.ini 配置文件

[main]
...
sessionManager = com.foo.my.SessionManagerImplementation
securityManager.sessionManager = $sessionManager

但是从头创建一个 SessionManager 是一件非常复杂的任务,大多数人都不愿去做。Shiro的开箱即用的 SessionManager 实现是高度可定制和配置的,同时满足大多数需要。本文档其余部分的大部分假设您将在介绍配置选项时使用Shiro的默认SessionManager实现,但是请注意,实际上您可以创建或插入几乎任何您想要的东西。

Session 超时

默认情况下,SessionManager 的默认会话超时时间是 30分钟。也就是说,如果任何 Session 创建后保持闲置(未使用,即 lastAccessedTime 没有更新)超过 30 分钟或更长,那么 Session 就可能过期,并且不允许再继续使用。

你可以设置默认的 session 超时时间,使用 globalSessionTimeout 属性来为所有的 session 定义默认的超时。例如,如果你希望超时时间是一小时而不是 30分钟:

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

单个 session 超时

globalSessionTimeout 限制所有新产生的 session 。你可以为每个 session 设置 timeout 属性。和上面的 globalSessionTimeout一样,这个值也是基于 毫秒的。

Session 监听器

Shiro 支持监听器的概念,允许你在一些非常重要的 session 事件发生时做出动作。你可以实现 SessionListener 接口(或 继承更方便的 SessionListenerAdapter)并且对 Session 操作做出相应的反应。

默认的 SessionManager的sessionListeners 属性 是一个集合,你可以给 SessionManager 配置一个或者多个 监听器实现:

[main]
...
aSessionListener = com.foo.my.SessionListener
anotherSessionListener = com.foo.my.OtherSessionListener

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

所有的 Session 事件

SessionListener 会监听所有的 session 事件,并不是只为了某一个 特定的session 。

Session 存储

不论session 什么时候创建或更新,它的数据都需要持久化到一个存储位置,这样才能让应用程序在接下来的操作中访问到。同样,当一个 Session 失效或者不再使用,也需要从存储空间中删除,以免存储空间耗尽。SessionManager 的实现可以将 session  的 CRUD操作委托给一个系统内部的组件,即 SessionDAO ,它遵从 Data Access Object (DAO)设计模式。

通过实现 SessionDAO 这个接口,你可以和任何你希望的数据存储进行交互。也就是说,你可以把你的 session 数据放到内存、或文件系统、或关系型数据库、或NoSQL 数据库中,或者其他任何地方。你可以完全掌控持久化行为。

你也可以配置任何形式的 SessionDAO 实现装载到默认的SessionManager 实例中,例如,像下面 shiro.ini 这样:

[main]
...
sessionDAO = com.foo.my.SessionDAO
securityManager.sessionManager.sessionDAO = $sessionDAO

当然,人们也期望,Shiro 已经准备了一些优秀的 SessionDAO 的实现,你可以开箱即用,或者继承他们做个性化处理。

Web 应用注意

上面的 securityManager.sessionManager.sessionDAO = $sessionDAO 装载方式只适用于当使用 Shiro 自己的 session 管理器的时候。Web 应用一般情况不使用这种本地session 管理器,而是保留 Servlet 容器的默认 session 管理器,然而这个管理器并不支持 Shiro 的SessionDAO。如果你希望在 Web 应用中使用 Shiro 提供的SessionDAO 接口来定制 session 存储或 session 集群,你必须首先配置一个Shiro 自己的web session 管理器。例如:

[main]
...
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionManager = $sessionManager

# Configure a SessionDAO and then set it:
securityManager.sessionManager.sessionDAO = $sessionDAO

(译者注:Shiro native 我翻译成了 Shiro 自己的,者应该是原文所表达的含义,即需要开发者在Web 应用中配置 Shiro 框架为 web应用专门定制的可以支持 SessionDAO 接口的 web session 管理器)

配置 SessionDAO 注意

Shiro 的默认配置 SessionManager 采用 in-memory-only 只读内存方式的Session 存储,这并不适用于大多数生产应用。大多数生产应用会想要配置EHChached 支持并且提供自己的 SessionDAO实现。注意, Web应用使用基于Servlet 容器的SessionManager 作为默认实例因此不用担心这个问题。这个问题只会在使用 Shiro 自己的SessionManager 的时候需要考虑。

EHCache SessionDAO

EHCache 不是默认可用的,但如果你不打算实现自己的 SessionDAO,那就强烈推荐为你的应用添加EHCache 来支持 Shiro 的Session 管理工作。EHCache SessionDAO 会将 session 存储到内存中,并支持当内存逐渐吃紧的情况下溢出到磁盘。这可以非常良好的保证生产应用不会在运行时随机 “丢失” Session。

使用 EHCache 作为你的默认选择

如果你没有自己定制化的 SessionDAO,一定(译者注:这里原文是推荐的口吻)要在你的Shiro 配置中使用EHCache 。EHCache 不仅可以使你的 Session 受益,同样也会对缓存鉴权、授权数据有所帮助。参考Chaching 文档获取更多帮助。

不依赖容器的 Session 集群

如果你迫切需要一个不依赖容器的 session 集群,那EHCache 同样是不错的选择。你可以显式插入一个 TerraCotta 到你的EHCache 中,并拥有一个不依赖容器的集群化的 session 缓存。再也不用担心什么Tomcat、JBoss、Jetty、WebSphere 或者 WebLogic  定制的session 集群了。

为 Session 启用EHCache 非常简单。首先,确保你的项目中已经有了 shiro-ehcache-<version>.jar 文件。

然后,下面的 shiro.ini 示例展示了如何使用 EHCache 支持所有 Shiro 缓存的需要(可不仅仅是 Session 支持哦):

[main]

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

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

最后一行,为所有 Shiro 的需要配置了一个 CacheManager。这个 CacheManager 实例会自动传播到 SessionDAO(默认实现了 CacheManagerWare 接口的 EnterpriseCacheSessionDAO )。

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

web 应用

不要忘记 SessionDAO 是Shiro 框架自己的SessionManager 实现所具备的特性。Web 应用默认使用 基于 Servlet 容器的 SessionManager 是不支持 SessionDAO 的。如果你想在web 应用中使用基于EHCache 的 Session 存储,就需要配置一个Shiro自己的 web SessionManager ,这已经在前面有所说明。

EHCache Session 缓存配置

http://shiro.apache.org/session-management.html#ehcache-session-cache-configuration

未完待续......

发布了191 篇原创文章 · 获赞 280 · 访问量 52万+

猜你喜欢

转载自blog.csdn.net/u014745069/article/details/101165717