shiro——会话管理

  5532c9c3945945a5a503ca6d1a0938dc.png一、会话管理

   Shiro提供了完整的企业级会话管理功能,不依赖于底层容器(如Tomcat、WebLogic),不管是J2SE还是J2EE环境都可以使用,提供了会话管理,会话事件监听,会话存储/持久化,容器无关的集群,失效/过期支持,对Web的透明支持,SSO单点登录的支持等特性。
  
  所谓会话,即用户访问应用时保持的连接关系,在多次交互中应用能够识别出当前访问的用户是谁,且可以在多次交互中保存一些数据。如访问一些网站时登录成功后,网站可以记住用户,且在退出之前都可以识别当前用户是谁。

88258c03e3c14fcba3fc7ad4997381aa.jpeg
  
 e45c1da62e86438d8390ddca178e7a42.png 1.基础组件

 

 d087b54db4aa47dfb15a3ee8b61d44e9.png1.1 SessionManager

  会话管理器管理着应用中所有 Subject 的会话的创建、维护、删除、失效、验证等工作。是Shiro 的核心组件,顶层组件SecurityManager直接继承了SessionManager,且提供了SessionsSecurityManager实现直接把会话管理委托给相应的SessionManager
  1)DefaultSessionManager:使用的默认实现,用于JavaSE环境
  2)ServletContainerSessionManager:使用的默认实现,用于Web环境,其直接使用Servlet容器的会话
  3)DefaultWebSessionManager:用于Web环境的实现,可以替代ServletContainerSessionManager,自己维护着会话,直接废弃了Servlet容器的会话管理

 d087b54db4aa47dfb15a3ee8b61d44e9.png1.2 SessionListener

  SessionListener会话监听器用于监听会话创建、过期及停止事件。
  实现方式:
          1)实现SessionListener,必须实现所有方法
          2)继承SessionListenerAdapter,重写指定方法

  
  相关API:
  1)onStart(Session session):监听会话创建事件
  2)onStop(Session session):监听会话销毁事件
  3)onExpiration(Session session):监听会话过期事件
 2e61e66a613c4598b13a0293e8ab54e1.png 1.3 SessionDao

  Shiro提供SessionDAO用于会话的CRUD,即DAO(Data Access Object)模式实现。

1)AbstractSessionDAO:提供了SessionDAO的基础实现,如生成会话ID等
  2)CachingSessionDAO:提供了对开发者透明的会话缓存的功能,需要设置相应的CacheManager 
  3)MemorySessionDAO:直接在内存中进行会话维护(默认方式)
  4)EnterpriseCacheSessionDAO:提供了缓存功能的会话维护,默认情况下使用MapCache实现,内部使用ConcurrentHashMap保存缓存的会话。

  相关API:

  //如DefaultSessionManager在创建完session后会调用该方法;
  //如保存到关系数据库/文件系统/NoSQL数据库;redis
  //即可以实现会话的持久化;返回会话ID;主要此处返回的
ID.equals(session.getId());  
 
Serializable create(Session session);
  //根据会话ID获取会话  
 
Session readSession(Serializable sessionId) throws UnknownSessionException;  
  //更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用  
  void update(Session session) throws UnknownSessionException;  
  //删除会话;当会话过期/会话停止(如用户退出时)会调用  
 
void delete(Session session);  
  //获取当前所有活跃用户,如果用户量多此方法影响性能  
 
Collection<Session> getActiveSessions();

  2e61e66a613c4598b13a0293e8ab54e1.png1.4 会话验证

  1)Shiro提供了会话验证调度器,用于定期的验证会话是否已过期,如果过期将停止会话。
  2)出于性能考虑,一般情况下都是获取会话的同时来验证会话是否过期并停止会话的;但是如果在Web环境中,如果用户不主动退出是不知道会话是否过期的,因此需要定义的检测会话是否过期,Shiro提供了会话验证调度器来定期检查会话是否过期,SessionValidationScheduler 。
  3)Shrio也提供了使用Quartz会话验证调度器 QuartzSessionValidationScheduler 。

14d798472ca04caeb976b1e250d318fb.png  1.5 案例

  1)创建Session ID生成器

 <!-- Session ID 生成器 -->
  <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator">
  </bean>

  2)自定义会话管理

  <!--sessionDao自定义会话管理,针对Session会话进行CRUD操作-->
  <bean id="customSessionDao" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO">
      <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
  </bean>

  3)创建会话监听器
 

 <!--会话监听器-->
  <bean id="shiroSessionListener" class="com.zking.ssm.book.shiro.ShiroSessionListener"/>

  4)会话cookie模板
 

<!--会话cookie模板-->
  <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
      <!--设置cookie的name-->
      <constructor-arg value="shiro.session"/>
      <!--设置cookie有效时间-->
      <property name="maxAge" value="-1"/>
      <!--设置httpOnly-->
      <property name="httpOnly" value="true"/>
  </bean>

  5)SessionManager会话管理器

 <!--SessionManager会话管理器-->
  <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
      <!--设置session会话过期时间 毫秒 3分钟=180000-->
      <property name="globalSessionTimeout" value="180000"/>
      <!--设置sessionDao-->
      <property name="sessionDAO" ref="customSessionDao"/>
      <!--设置间隔多久检查一次session的有效性 默认60分钟-->
      <property name="sessionValidationInterval" value="1800000"/>
      <!--配置会话验证调度器-->
      <!--<property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>-->
      <!--是否开启检测,默认开启-->
      <!--<property name="sessionValidationSchedulerEnabled" value="true"/>-->
      <!--是否删除无效的session,默认开启-->
      <property name="deleteInvalidSessions" value="true"/>
      <!--配置session监听器-->
      <property name="sessionListeners">
          <list>
              <ref bean="shiroSessionListener"/>
          </list>
      </property>
      <!--会话Cookie模板-->
      <property name="sessionIdCookie" ref="sessionIdCookie"/>
      <!--取消URL后面的JSESSIONID-->
      <property name="sessionIdUrlRewritingEnabled" value="false"/>
  </bean>

  5532c9c3945945a5a503ca6d1a0938dc.png二、缓存管理

 531215d74d244d358b516adcf9004c40.png 1.为什么要使用缓存

  在没有使用缓存的情况下,我们每次发送请求都会调用一次doGetAuthorizationInfo方法来进行用户的授权操作,但是我们知道,一个用户具有的权限一般不会频繁的修改,也就是每次授权的内容都是一样的,所以我们希望在用户登录成功的第一次授权成功后将用户的权限保存在缓存中,下一次请求授权的话就直接从缓存中获取,这样效率会更高一些。


  531215d74d244d358b516adcf9004c40.png2.什么是ehcache

  Ehcache是现在最流行的纯Java开源缓存框架,配置简单、结构清晰、功能强大。是Hibernate中默认CacheProvider。Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。
   
  注1:本章介绍的是2.X版本,3.x的版本和2.x的版本API差异比较大

  531215d74d244d358b516adcf9004c40.png3.ehcache特点 

1) 够快
      Ehcache的发行有一段时长了,经过几年的努力和不计其数的性能测试,Ehcache终被设计于large, high concurrency systems.
  2) 够简单
      开发者提供的接口非常简单明了,从Ehcache的搭建到运用运行仅仅需要的是你宝贵的几分钟。其实很多开发者都不知道自己用在用Ehcache,Ehcache被广泛的运用于其他的开源项目
  3) 够袖珍
      关于这点的特性,官方给了一个很可爱的名字small foot print ,一般Ehcache的发布版本不会到2M,V 2.2.3 才 668KB。
  4) 够轻量
      核心程序仅仅依赖slf4j这一个包,没有之一!
  5) 好扩展
      Ehcache提供了对大数据的内存和硬盘的存储,最近版本允许多实例、保存对象高灵活性、提供LRU、LFU、FIFO淘汰算法,基础属性支持热配置、支持的插件多
  6) 监听器
      缓存管理器监听器 (CacheManagerListener)和 缓存监听器(CacheEvenListener),做一些统计或数据一致性广播挺好用的
  7) 分布式缓存
      从Ehcache 1.2开始,支持高性能的分布式缓存,兼具灵活性和扩展性

  531215d74d244d358b516adcf9004c40.png4.ehcache入门

b89de1a451c04059873f6f9289c6523c.png  1)导入相关依赖

 <dependency>
     <groupId>net.sf.ehcache</groupId>
     <artifactId>ehcache</artifactId>
     <version>2.10.0</version>
  </dependency>

 258cef90f8c74a14b35c72d90cff8cd9.png 2)核心接口

  CacheManager:缓存管理器
  Cache:缓存对象,缓存管理器内可以放置若干cache,存放数据的实质,所有cache都实现了Ehcache接口
  Element:单条缓存数据的组成单位

  CacheManager -> Cache(可定义各种缓存策略) -> Element

  7cce8e9495ca4fa58912b0f4b12acfbe.png3)核心配置文件 ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    <!--
       diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
       user.home – 用户主目录
       user.dir  – 用户当前工作目录
       java.io.tmpdir – 默认临时文件路径
     -->
    <diskStore path="java.io.tmpdir/Tmp_EhCache"/>
    <!--
       defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
     -->
    <!--
      name:缓存名称。
      maxElementsInMemory:缓存最大数目
      maxElementsOnDisk:硬盘最大缓存个数。
      eternal:对象是否永久有效,一但设置了,timeout将不起作用。
      overflowToDisk:是否保存到磁盘,当系统当机时
      timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
      timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
      diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
      diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
      diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
      memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
      clearOnFlush:内存数量最大时是否清除。
      memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
      FIFO,first in first out,这个是大家最熟的,先进先出。
      LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
      LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
   -->
    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="259200"
            memoryStoreEvictionPolicy="LRU"/>
 
    <cache
            name="cloud_user"
            eternal="false"
            maxElementsInMemory="5000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="1800"
            memoryStoreEvictionPolicy="LRU"/>
 
</ehcache>

  531215d74d244d358b516adcf9004c40.png5.shiro与ehcache整合

  4310c7b8073848d0adfbe87ca635dde2.png1)导入相关依赖(注意:这里使用shiro的1.4.1版本)

  注:之前是使用的1.3.1版本,在安全退出的时候引发了UnknownSessionException: There is no session with id错误,通过升级shiro版本后问题解决!!!o(╥﹏╥)o 一下午时间啊!!!

  <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-ehcache</artifactId>
      <version>1.4.1</version>
  </dependency>

  <!-- spring对ehcache的相关支持-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>

  4310c7b8073848d0adfbe87ca635dde2.png2)实现spring与ehcache缓存创建spring-ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache-3.2.xsd">
 
  <description>ehcache缓存配置管理文件</description>
 
  <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="configLocation" value="classpath:ehcache/ehcache.xml"/>
  </bean>
 
  <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
    <property name="cacheManager" ref="ehcache"/>
  </bean>
 
  <!-- 启用缓存注解开关 -->
  <cache:annotation-driven cache-manager="cacheManager"/>
</beans>

 使用ehcache缓存

 <!--使用ehcache缓存-->
  <bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
      <property name="configLocation" value="classpath:ehcache.xml"/>
      <property name="shared" value="true"/>
  </bean>
  <!-- 默认是cacheManager -->
  <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
      <property name="cacheManager" ref="cacheManagerFactory"/>
  </bean>

  4310c7b8073848d0adfbe87ca635dde2.png3)在SecurityManager安全管理器中设置缓存管理器

  <!--设置缓存管理器-->
  <property name="cacheManager" ref="cacheManager"/>

  4)开启Shiro的授权或者认证数据缓存
  
  在自定义Realm配置中开启并设置授权或者认证数据缓存

 

 <!--开启缓存-->
  <property name="cachingEnabled" value="true"/>
  <!--开启授权缓存-->
  <property name="authorizationCachingEnabled" value="true"/>
  <!--设置ehcache的中的缓存对象名-->
  <property name="authorizationCacheName" value="shiroAuthzCache"/>


  注:这里只开启了授权缓存,避免每次请求都要重新查询授权数据!!!


 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值