Shiro 提供了一个完整的企业级会话管理解决方案,不再依赖web容器。可以在web和非web环境下使用。
1、Shiro的session特性
1)基于POJO/J2SE:shiro中session相关的类都是基于接口实现的简单的java对象(POJO),兼容所有java对象的配置方式,扩展也更方便,完全可以定制自己的会话管理功能 。
2)简单灵活的会话存储/持久化:因为shiro中的session对象是基于简单的java对象的,所以你可以将session存储在任何地方,例如,文件,各种数据库,内存中等。
3)容器无关的集群功能:shiro中的session可以很容易的集成第三方的缓存产品完成集群的功能。例如,Ehcache + Terracotta, Coherence, GigaSpaces等。你可以很容易的实现会话集群而无需关注底层的容器实现。
4)异构客户端的访问:可以实现web中的session和非web项目中的session共享。
5)会话事件监听:提供对对session整个生命周期的监听。
6)保存主机地址:在会话开始session会存用户的ip地址和主机名,以此可以判断用户的位置。
7)会话失效/过期的支持:用户长时间处于不活跃状态可以使会话过期,调用touch()方法,可以主动更新最后访问时间,让会话处于活跃状态。
8)透明的Web支持:shiro全面支持Servlet 2.5中的session规范。这意味着你可以将你现有的web程序改为shiro会话,而无需修改代码。
9)SSO单点登录的支持:shiro session基于普通java对象,使得它更容易存储和共享,可以实现跨应用程序共享。可以根据共享的会话,来保证认证状态到另一个程序。从而实现单点登录。
2、使用会话
会话: 即用户访问应用时保持的连接关系,在多次交互中应用能够识别出当前访问的用户是谁,且可以在多次交互中保存一些数据。
Shiro的会话支持不仅可以在普通的JavaSE应用中使用,也可以在JavaEE应用中使用,如web应用。且使用方式是一致的。
建议在开发中:Controller层使用原生的HttpSession对象,在Service层中使用Shiro提供的Session对象。如果在Service层中使用HttpSession对象,那么属于侵入式,并不建议这么做。Shiro提供的Session能够很好的解决这个问题。
可以从当前的Subject中获取会话:
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
会话相关API:
返回值方法名描述ObjectgetAttribute(Object key) 根据key标识返回绑定到session的对象CollectiongetAttributeKeys() 获取在session中存储的所有的keyStringgetHost()获取当前主机ip地址,如果未知,返回nullSerializablegetId() 获取session的唯一idDategetLastAccessTime() 获取最后的访问时间DategetStartTimestamp() 获取session的启动时间longgetTimeout() 获取session失效时间,单位毫秒voidsetTimeout(long maxIdleTimeInMillis) 设置session的失效时间ObjectremoveAttribute(Object key) 通过key移除session中绑定的对象voidsetAttribute(Object key, Object value) 设置session会话属性voidstop() 销毁会话voidtouch() 更新会话最后访问时间① Subject.getSession()
获取会话,等价于Subject.getSession(true),即如果当前没有创建session对象会创建一个;Subject.getSession(false),如果当前没有创建session对象则返回null。
② session.getStartTimestamp() & session.getLastAccessTime()
获取会话的启动时间及最后访问时间;如果是J2SE环境需要自己定期调用session.touch()去更新最后访问时间;如果是Web环境,每次进入ShiroFilter都会自动调用session.touch()来更新最后访问时间。
③ session.touch() & session.stop()
更新会话最后访问时间以及销毁会话;Subject.logout()会自动调用session.stop()。在Web应用中,调用HttpSession.invalidate()也会自动调用session.stop()来销毁shiro的会话。
3、会话管理器
SessionManager 管理所有 Subject 的session包括创建、维护、删除、失效、验证等工作。SessionManager 是顶层组件,由 SecurityManager 管理。
SecurityManager 的实现类 DefaultSecurityManager 及 DefaultWebSecurityManager 继承了 SessionsSecurityManager。
SessionsSecurityManager 可以把相应的会话管理委托给 SessionManager。
SecurityManager提供了如下接口:
Session start(SessionContext context); //启动会话
Session getSession(SessionKey key) throws SessionException; //根据会话Key获取会话
另外用于Web环境的WebSessionManager又提供了如下接口:
boolean isServletContainerSessions();//是否使用Servlet容器的会话
Shiro还提供了ValidatingSessionManager用于验资并过期会话:
void validateSessions();//验证所有会话是否过期
配置会话:
securityManager.sessionManager=$sessionManager
4、会话监听器:
自己的监听器,需要实现 SessionListener 接口
① onStart(Session)
监听会话创建事件
② onStop(Session)
监听会话销毁事件
③ onExpiration(Session)
监听会话过期事件
5、会话存储/持久化
Shiro提供SessionDAO用于会话的CRUD,即DAO(Data Access Object)模式实现。
① AbstractSessionDAO 提供了 SessionDAO 的基础实现,如生成会话ID等。
② CachingSessionDAO 提供了对开发者透明的会话缓存的功能,需要设置相应的 CacheManager。
③ MemorySessionDAO 直接在内存中进行会话维护。
④ EnterpriseCacheSessionDAO 提供了缓存功能的会话维护,默认情况下使用 MapCache 实现,内部使用 ConcurrentHashMap 保存缓存的会话。
6、会话验证
① Shiro提供了会话验证调度器,用于定期的验证会话是否已过期,如果过期将停止会话。
② 出于性能考虑,一般情况下都是获取会话的同时来验证会话是否过期并停止会话的;但是如果在Web环境中,如果用户不主动退出是不知道会话是否过期的,因此需要定义的检测会话是否过期,Shiro提供了会话验证调度器来定期检查会话是否过期,SessionValidationScheduler 。
③ Shrio也提供了使用 Quartz 会话验证调度器 QuartzSessionValidationScheduler 。
使用 Quartz 时需要导入 shiro-quartz 依赖:
org.apache.shiro
shiro-quartz
1.4.0
参考文章:
https://blog.csdn.net/ljxbbss/article/details/77771001
https://www.cnblogs.com/startcaft/p/7456933.html
end ~