第十章:Shiro的Cache——深入浅出学Shiro细粒度权限开发框架
概述
Shiro开发团队明白在许多应用程序中性能是至关重要的。Caching 是Shiro 中的一个重要功能,以确保安全操作保持尽可能的快。
但是,Shiro并不实现缓存的功能,Shiro 的缓存支持基本上是一个抽象的(包装)API,它将“坐”在一个基本的缓存机制产品(例如,Ehcache,OSCache,Terracotta,Coherence,GigaSpaces,JBossCache 等)之上。这允许Shiro终端用户配置他们喜欢的任何缓存机制。
Caching API
Shiro 有三个重要的缓存接口:
1:CacheManager - 负责所有缓存的主要管理组件,它返回Cache 实例
2:Cache - 维护key/value 对
3:CacheManagerAware - 通过想要接收和使用CacheManager 实例的组件来实现
CacheManager 返回Cache 实例,各种不同的Shiro 组件使用这些Cache 实例来缓存必要的数据。任何实现了CacheManagerAware 的Shiro 组件将会自动地接收一个配置好的CacheManager,该CacheManager 能够用来获取Cache 实例。
Shiro 的SecurityManager 实现及所有AuthorizingRealm实现都实现了CacheManagerAware
Shiro 提供了一个个立即可用的EhCacheManager 实现
Caching 配置
n通过在SecurityManager上设置了CacheManger,它反过来也会将它设置到实现了CacheManagerAware 的各种不同的Realm 上,示例如下:
cacheManager = org.apache.shiro.cache.ehcache.EhcacheManager
securityManager.cacheManager = $cacheManager
默认的EHCache使用一个Shiro特定的ehcache.xml文件来配置,大致内容如下:
<cache name="shiro-activeSessionCache"
maxElementsInMemory="10000"
overflowToDisk="true"
eternal="true"
timeToLiveSeconds="0"
timeToIdleSeconds="0"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="600"/>
包装使用其他的Cache框架
可以通过写一个类来实现Shiro的CacheManager,在这个类里面包装使用任何你想要使用的Cache框架,这里以使用Srping的缓存框架为例,参考如下:
public class MyCacheManager implements CacheManager {
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
org.springframework.cache.Cache springCache = cacheManager.getCache(name);
return new SpringCacheWrapper(springCache);
}
class SpringCacheWrapper implements Cache {
private org.springframework.cache.Cache springCache;
SpringCacheWrapper(org.springframework.cache.Cache springCache) {
this.springCache = springCache;
}
public Object get(Object key) throws CacheException {
Object value = springCache.get(key);
if (value instanceof SimpleValueWrapper) {
return ((SimpleValueWrapper) value).get();
}
return value;
}
//等等,还有几个需要实现的方法,都可以使用你要使用的缓存框架去实现
}
}
缓存数据同步更新的解决方案
使用Shiro的时候,缓存数据最大的问题就在于数据同步更新。
因为Shiro只负责验证部分,如果应用程序修改了人员的权限,那么就需要同步更新到Shiro里面去,也就是要同步Shiro的缓存数据。
一个解决方案就是完全废弃Shiro的缓存机制,自己在应用中控制数据的缓存
这里给出另一种简易可行的方案:
1:如果你使用的Spring,而且是自定义的Realm,那么可以在你的Realm里面添加一个方法来删除该用户的缓存数据,这样下次shiro在验证这个用户的时候,就会重新去获取数据,从而实现数据的同步
2:由于是自定义的Realm,可以把该对象作为Spring的bean,注入到你的业务对象中,在需要的时候就可以调用该方法来删除shiro的缓存数据了
示例,比如在前面自定义的MyRealm中,添加如下方法,示例如下:
public void removeUserCache(String userId){
SimplePrincipalCollection pc = new SimplePrincipalCollection();
pc.add(userId, super.getName());
super.clearCachedAuthorizationInfo(pc);
}
然后在HelloAnno中进行测试,示例如下:
1:要注入MyRealm,但注意需要使用getter/setter来注入
2:在main方法中,示例如下:
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
HelloAnno t = (HelloAnno)ctx.getBean("helloAnno");
t.login();
t.t();
t.t();
t.getMr().removeUserCache("javass");
t.t();
}
- Web应用渗透测试-本地文件包含
- shiro权限控制(二):分布式架构中shiro的实现
- Groovy实现原理分析——准备工作
- HBCTF第一场2个pwn题的简单分析
- ACM竞赛之输入输出(以C与C++为例)
- 能让程序做的事情坚决不用人来做——批量修复markdownlint MD034警告
- swift demo1 tableview
- Swift Alamofire
- 给Ocelot做一个Docker 镜像
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](十一)
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](十)
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](九)
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](八)
- 第二届ZCTF逆向题分析(一)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- LeetCode(1)-找出数组中重复的数字
- LeetCode(面试题:二维数组中的查找)
- 面试题05-替换空格(LeeCode)
- 解决Mybatis当实体类中的属性名和表中的字段名不一致的问题
- 图书管理系统(一)项目框架结构搭建
- Mybatis中模糊查询like语句的使用方法
- win10暴力查看wifi密码
- 再也不怕面试官问java中的goto关键字了?
- 死磕Java之分析short类型
- 死磕Java之Java数据类型的来龙去脉
- 请不要再使用判断进行参数校验了
- 检测假新闻:比较不同的分类方法的准确率
- SpringBoot下载xlsx模板,导出excel数据
- 如何利用机器学习和Gatsby.js创建假新闻网站
- Spring Security 实战干货: 401和403状态