目录

一、概述

二、Shiro集成Redis实现缓存

三、Shiro集成Ehcache实现缓存

四、总结


一、概述

Shiro 提供了类似于 Spring 的 Cache 抽象,即 Shiro 本身不实现 Cache,但是对 Cache 进行了又抽象,方便更换不同的底层 Cache 实现。

Shiro 提供的 Cache 接口:

public interface Cache<K, V> {//根据Key获取缓存中的值public V get(K key) throws CacheException;//往缓存中放入key-value,返回缓存中之前的值public V put(K key, V value) throws CacheException; //移除缓存中key对应的值,返回该值public V remove(K key) throws CacheException;//清空整个缓存public void clear() throws CacheException;//返回缓存大小public int size();//获取缓存中所有的keypublic Set<K> keys();//获取缓存中所有的valuepublic Collection<V> values();
}

Shiro 提供的 CacheManager 接口:

public interface CacheManager {//根据缓存名字获取一个Cachepublic <K, V> Cache<K, V> getCache(String name) throws CacheException;
}

Shiro 还提供了 CacheManagerAware 用于注入 CacheManager:

public interface CacheManagerAware {//注入CacheManagervoid setCacheManager(CacheManager cacheManager);
}

Shiro 内部相应的组件(DefaultSecurityManager)会自动检测相应的对象(如 Realm)是否实现了 CacheManagerAware 并自动注入相应的 CacheManager。

在上一篇文章【使用Shiro实现用户授权功能】中,我们通过在doGetAuthorizationInfo(PrincipalCollection principalCollection)方法中,每次都去查询用户对应的角色和权限信息,实际上对于一个用户来说,其权限在短时间内基本是不会变化的。因此,Shiro提供了缓存功能,可以将权限缓存起来,避免频繁访问数据库获取权限信息,本篇文章主要介绍基于Redis和Ehcache缓存的实现,下面我们来看具体的实现。

二、Shiro集成Redis实现缓存

【a】引入redis-shiro依赖

<!-- shiro-redis -->
<dependency><groupId>org.crazycake</groupId><artifactId>shiro-redis</artifactId><version>2.4.2.1-RELEASE</version>
</dependency>
<!-- 对象池,使用redis时必须引入 -->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>
</dependency>

【b】application.yml中加入redis的配置

spring:redis:host: localhostport: 6379timeout: 0mslettuce:pool:# 连接池最大连接数(使用负值表示没有限制) 默认 8max-active: 8# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1max-wait: -1ms# 连接池中的最大空闲连接 默认 8max-idle: 8# 连接池中的最小空闲连接 默认 0min-idle: 0

【c】在Shiro全局配置类中配置Redis缓存管理器以及redis管理器

/*** 配置Redis缓存管理器*/
@Bean
public RedisCacheManager redisCacheManager() {RedisCacheManager redisCacheManager = new RedisCacheManager();//设置redis管理器redisCacheManager.setRedisManager(redisManager());return redisCacheManager;
}/*** 配置redis管理器*/
@Bean
public RedisManager redisManager() {RedisManager redisManager = new RedisManager();//设置一小时超时,单位是秒redisManager.setExpire(3600);return redisManager;
}

【d】将Redis缓存管理器加入给SecurityManager安全管理器管理

//设置缓存管理器
defaultWebSecurityManager.setCacheManager(redisCacheManager());

【e】新增一个需要访问权限的接口

@RequiresPermissions(value = "user:list")
@RequestMapping("/userList")
public String userList(){return "userList";
}

新建userList.html:

<!doctype html><!--注意:引入thymeleaf的名称空间-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body>
userList page
</body>
</html>

success.html中加入如下超链接:

<div>跳转到userList.html: <a href="/userList">userList.html</a><br></div>

【f】启动项目

Caused by: java.lang.ClassNotFoundException: org.apache.shiro.event.EventBusat java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_121]at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_121]at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_121]at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_121]... 25 common frames omitted

可见,项目启动报错:ClassNotFoundException: org.apache.shiro.event.EventBus。因为Maven依赖的jar包中缺少了EventBus这个class文件,原来maven工程中已经依赖了shiro-core1.4.0的版本 ,在shiro-redis依赖中使用了shiro-core-1.2版本,把1.4版本的排除了出去, 而这个类要在1.3版本上才有,所以需要排除1.2版本。

<!-- shiro-redis -->
<dependency><groupId>org.crazycake</groupId><artifactId>shiro-redis</artifactId><version>2.4.2.1-RELEASE</version><exclusions><exclusion><artifactId>shiro-core</artifactId><groupId>org.apache.shiro</groupId></exclusion></exclusions>
</dependency>

重新启动项目,这次启动没有报错了,但是当你访问list.html页面时,页面报如下的错误:

tried to access method redis.clients.jedis.JedisPool.returnResource

翻译一下,其实指的就是尝试从类org.crazycake.shiro.RedisManager访问方法,但是访问不到。

原因其实是redis.clients:jedis:3.1.0版本种的returnResource()方法访问修饰符变为protected,所以我们换低一点的版本即可:

<dependency><groupId>org.crazycake</groupId><artifactId>shiro-redis</artifactId><version>2.4.2.1-RELEASE</version><exclusions><exclusion><artifactId>shiro-core</artifactId><groupId>org.apache.shiro</groupId></exclusion><exclusion><artifactId>shiro-core</artifactId><groupId>org.apache.shiro</groupId></exclusion><exclusion><artifactId>jedis</artifactId><groupId>redis.clients</groupId></exclusion></exclusions>
</dependency>
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version>
</dependency>

再次重启项目,使用admin/123456进行登录:

依次访问userList.html和list.html两个需要授权的页面,如下图:

注意:需要首先启动好Redis服务,否则项目连不上Redis,会报错。

如下图,可以看到后台只打印出一次从数据库查询获取权限的日志信息,证明我们的redis缓存起效果。

以上就是关于Shiro整合Redis实现用户权限缓存功能,接下来我们再来看另外一种实现方式:Shiro整合Ehcache实现用户权限缓存功能。

三、Shiro集成Ehcache实现缓存

【a】引入Shiro跟Ehcachae整合相关依赖

<!-- shiro ehcache -->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>1.3.2</version>
</dependency>
<!-- ehchache -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId>
</dependency>

【b】新建Ehcache配置文件

在resource/config路径下新建shiro-ehcache-config.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 path="java.io.tmpdir/Tmp_EhCache"/><!--defaultCache:默认的缓存配置信息,如果不加特殊说明,则所有对象按照此配置项处理maxElementsInMemory:设置了缓存的上限,最多存储多少个记录对象eternal:代表对象是否永不过期timeToIdleSeconds:最大的发呆时间timeToLiveSeconds:最大的存活时间overflowToDisk:是否允许对象被写入到磁盘--><defaultCachemaxElementsInMemory="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="false"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"/><!--cache:为指定名称的对象进行缓存的特殊配置name:指定对象的完整名--><!-- 登录记录缓存锁定1小时 --><cachename="passwordRetryCache"maxEntriesLocalHeap="2000"eternal="false"timeToIdleSeconds="3600"timeToLiveSeconds="0"overflowToDisk="false"statistics="true"/></ehcache>

【c】Shiro全局配置类中配置Ehcache

/*** Ehcache缓存管理器* @return*/
@Bean
@Primary  //指定ehcache为主要的缓存管理器
public EhCacheManager ehCacheManager() {EhCacheManager ehCacheManager = new EhCacheManager();ehCacheManager.setCacheManagerConfigFile("classpath:config/shiro-ehcache-config.xml");return ehCacheManager;
}

【d】将缓存对象注入到SecurityManager中

//设置EhCacheManager缓存管理员
defaultWebSecurityManager.setCacheManager(ehCacheManager());

【e】启动项目测试

使用admin/123456进行登录:

依次访问userList.html和list.html两个需要授权的页面,如下图:

如下图,可以看到后台只打印出一次从数据库查询获取权限的日志信息,同样证明我们的ehcache缓存起效果。

注意,需要注释掉前面在shiro全局配置类中注入的redis缓存,否则启动会报错:因为发现两个缓存管理器。当然如果不注释的话,也可以使用@Primary注解指定某个缓存管理器为主要的管理器。

扩展知识:

Ehcache的配置详细说明如下:

(一)、以下属性是必须的:

  1、name: Cache的名称,必须是唯一的(ehcache会把这个cache放到HashMap里)。

  2、maxElementsInMemory:在内存中缓存的element的最大数目。

  3、maxElementsOnDisk:在磁盘上缓存的element的最大数目,默认值为0,表示不限制。

  4、eternal:设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断。

  5、overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上。

(二)、以下属性是可选的:

  1、timeToIdleSeconds: 对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问。

  2、timeToLiveSeconds: 对象存活时间,指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问。

  3、diskPersistent: 是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false。

  4、diskExpiryThreadIntervalSeconds: 对象检测线程运行时间间隔。标识对象状态的线程多长时间运行一次。

  5、diskSpoolBufferSizeMB: DiskStore使用的磁盘大小,默认值30MB。每个cache使用各自的DiskStore。

  6、memoryStoreEvictionPolicy: 如果内存中数据超过内存限制,向磁盘缓存时的策略。默认值LRU,可选FIFO、LFU。

(三)、缓存的3 种清空策略 :

  1、FIFO ,First In First Out (先进先出);

  2、LFU , Less Frequently Used (最少使用)。意思是一直以来最少被使用的。缓存的元素有一个hit 属性,hit 值最小的将会被清出缓存;

  3、LRU ,Least Recently Used(最近最少使用)。 (ehcache 默认值).缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存;

四、总结

本篇文章主要总结了Shiro提供的缓存功能,能大大减少授权的时候对数据库的查询,通过配置两种缓存管理器:Redis和Ehcache缓存管理器。在实际项目中,可以根据需求配置两种缓存管理器,实现用户高效授权操作。

【Shiro第六篇】SpringBoot + Shiro集成缓存功能相关推荐

  1. 七十六、SpringBoot 的数据缓存cache+Redis(三)

    @Author:Runsen 来源:尚硅谷 下面建议读者学习尚硅谷的B站的SpringBoot视频,我是学雷丰阳视频入门的. 具体链接如下:B站尚硅谷SpringBoot教程 文章目录 Redis P ...

  2. 【Shiro】六、Apache Shiro Session管理

    1.Session的介绍 关于Session 会话:从启动一个Session到关闭这个Session作为一个会话,是对客户端和服务器端交互的一种封装,带有时效性 会话的产生: 一般从容器中产生 Web ...

  3. Shiro第四篇【Shiro与Spring整合、快速入门、Shiro过滤器、登陆认证】

    Spring与Shiro整合 导入jar包 shiro-web的jar. shiro-spring的jar shiro-code的jar 快速入门 shiro也通过filter进行拦截.filter拦 ...

  4. springboot+shiro+redis+jwt实现多端登录:PC端和移动端同时在线(不同终端可同时在线)

    前言 之前写了篇 springboot+shiro+redis多端登录:单点登录+移动端和PC端同时在线 的文章,但是token用的不是 jwt 而是 sessionID,虽然已经实现了区分pc端和移 ...

  5. SpringBoot集成Shiro前后端分离使用redis做缓存

    文章目录 一 .shiro介绍 1.基础介绍 2.基本功能点 3.基本流程图 二. 常用的权限管理表关系 2.1. 表组成 2.2. 表结构 三.实战案例 3.1. 案例介绍 3.2. 依赖 3.3. ...

  6. springboot shiro和freemarker集成之权限控制完全参考手册(跳过认证,登录由三方验证,全网首发)...

    本文主要考虑单点登录场景,登录由其他系统负责,业务子系统只使用shiro进行菜单和功能权限校验,登录信息通过token从redis取得,这样登录验证和授权就相互解耦了. 用户.角色.权限进行集中式管理 ...

  7. Shiro和SpringBoot简单集成

    Shiro是一种简单的安全框架,可以用来处理系统的登录和权限问题. 本篇记录一下Spring Boot和Shiro集成,并使用Jwt Token进行无状态登录的简单例子. 参考Demo地址,此Demo ...

  8. Spring Boot教程(十六):Spring Boot集成shiro

    Apache Shiro™是一个功能强大且易于使用的Java安全框架,可执行身份验证,授权,加密和会话管理.借助Shiro易于理解的API,您可以快速轻松地保护任何应用程序 - 从最小的移动应用程序到 ...

  9. SpringBoot系列 - 集成Shiro权限管理

    Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,相比Spring Security而言相当简单, 可能没有Spring Security做的功能强大, ...

  10. Shiro教程_2 Shiro+SpringBoot+Mysql+Redis(缓存)

    源代码 https://gitee.com/fakerlove/Shiro Shiro+SpringBoot+Mysql+Redis(缓存) 1. 添加依赖 <?xml version=&quo ...

最新文章

  1. playframework学习笔记1 -- 开发环境和第一个工程
  2. Kafka日志清理之Log Deletion
  3. RocketMQ消息轨迹-设计篇
  4. 天平应什么放置_电子天平讲义全解(使用/维护/分类)
  5. Rabin-Karp字符串查找算法学习:poj1200
  6. 带有LLVM的eBPF组件
  7. 用Unity的Animation播放Animator动画Clip
  8. as 与 is 的区别
  9. 真正优秀的人是如何度过假期的
  10. button执行onclick函数_JavaScript 函数定义与调用
  11. 论大学学霸是怎样炼成的……
  12. python调用百度云文字识别
  13. pyhton——爬小说网站(顶点最强国防生)
  14. LensFlare Studio for Mac 6.3 镜头光晕特效软件 破解版下载
  15. 虚拟数字人营销时代来临,虚拟主播与真人主持直播间同台互动
  16. 图表说话之解析excel商务饼图做法
  17. 计算机无法连接到宽带,win10提示无法连接到宽带连接不能建立到远程计算机怎么解决...
  18. Appium 常用初始化启动参数 Capability详解
  19. 月薪40K起,什么是Python全栈工程师?全栈工程师薪资为何这么高?
  20. Using Sketch with Framer 使用Sketch与Framer Lynda课程中文字幕

热门文章

  1. java匿名内部类 内部类_java中的匿名内部类详细总结
  2. 计算机信息与自然科学,郑旭飞 - 计算机与信息科学学院 - Powered by 西南大学
  3. 机器学习- 吴恩达Andrew Ng Week9 知识总结 Recommender Systems
  4. 极客大学架构师训练营 数据结构与算法 平衡二叉树 红黑树 动态规划 遗传算法 第15课 听课总结
  5. 服务器系统更新失败进不了系统,第五人格更新后进不去怎么办 更新连接服务器失败...
  6. 2021-09-1427. 移除元素
  7. 从有序数组中找出某个数出现的次数
  8. 谷歌浏览器翻译设置_谷歌翻译网站最近有点“小脾气”
  9. 【知识图谱系列】GCNII模型探索DeepGNN的Over-Smoothing问题
  10. android studio for android learning (十一) 利用bundle在activity之间进行数据传递示例