shiro原理_java:shiro高级篇——1
第六章 Realm缓存机制
1、Realm缓存机制意义
在上面我们自定了自己的realm,但是我们发现
在认证和授权的时候,程序需要频繁的访问数据库,这样对于数据库的压力可想而知,那我们怎么处理呢?
2、Realm缓存机制实现思路
【1】缓存机制图解
【2】原理分析
此时我们对UserBridgeServiceImpl的实现类里面的逻辑加入了自定义的SimpleCacheService缓存服务接口,简单来说实现了在认证和鉴权时不需要每次都去查询数据库,而是把认证和鉴权信息放入到redis缓存中,以减低数据库的访问压力
1、集成redis服务器,作为集中存储认证和鉴权信息 2、改写UserBridgeServiceImpl使其优先从缓存中读取
3、redission集成
【1】添加ShiroRedisProperties
此类主要负责yaml文件的配置类
package com.itheima.shiro.config;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import java.io.Serializable;/** * @Description redis配置文件 */@Data@ConfigurationProperties(prefix = "itheima.framework.shiro.redis")public class ShiroRedisProperties implements Serializable { /** * redis连接地址 */ private String nodes ; /** * 获取连接超时时间 */ private int connectTimeout ; /** * 连接池大小 */ private int connectPoolSize; /** * 初始化连接数 */ private int connectionMinimumidleSize ; /** * 等待数据返回超时时间 */ private int timeout ; /** * 全局超时时间 */ private long globalSessionTimeout;}
【2】编辑ShiroConfig
集成redisson的相关配置,同时启用ShiroRedisProperties的配置
package com.itheima.shiro.config;import com.itheima.shiro.core.ShiroDbRealm;import com.itheima.shiro.core.impl.ShiroDbRealmImpl;import com.itheima.shiro.filter.RolesOrAuthorizationFilter;import com.itheima.shiro.properties.PropertiesUtil;import lombok.extern.log4j.Log4j2;import org.apache.shiro.spring.LifecycleBeanPostProcessor;import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.apache.shiro.web.servlet.SimpleCookie;import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;import org.redisson.Redisson;import org.redisson.api.RedissonClient;import org.redisson.config.Config;import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.DependsOn;import javax.servlet.Filter;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;/** * @Description 权限配置类 */@Configuration@ComponentScan(basePackages = "com.itheima.shiro.core")@EnableConfigurationProperties({ShiroRedisProperties.class})@Log4j2public class ShiroConfig { @Autowired private ShiroRedisProperties shiroRedisProperties; /** * @Description redission客户端 */ @Bean("redissonClientForShiro") public RedissonClient redissonClient() { log.info("=====初始化redissonClientForShiro开始======"); String[] nodeList = shiroRedisProperties.getNodes().split(","); Config config = new Config(); if (nodeList.length == 1) { config.useSingleServer().setAddress(nodeList[0]) .setConnectTimeout(shiroRedisProperties.getConnectTimeout()) .setConnectionMinimumIdleSize(shiroRedisProperties.getConnectionMinimumidleSize()) .setConnectionPoolSize(shiroRedisProperties.getConnectPoolSize()).setTimeout(shiroRedisProperties.getTimeout()); } else { config.useClusterServers().addNodeAddress(nodeList) .setConnectTimeout(shiroRedisProperties.getConnectTimeout()) .setMasterConnectionMinimumIdleSize(shiroRedisProperties.getConnectionMinimumidleSize()) .setMasterConnectionPoolSize(shiroRedisProperties.getConnectPoolSize()).setTimeout(shiroRedisProperties.getTimeout()); } RedissonClient redissonClient = Redisson.create(config); log.info("=====初始化redissonClientForShiro完成======"); return redissonClient; } /** * @Description 创建cookie对象 */ @Bean(name="sessionIdCookie") public SimpleCookie simpleCookie(){ SimpleCookie simpleCookie = new SimpleCookie(); simpleCookie.setName("ShiroSession"); return simpleCookie; } /** * @Description 权限管理器 * @param * @return */ @Bean(name="securityManager") public DefaultWebSecurityManager defaultWebSecurityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(shiroDbRealm()); securityManager.setSessionManager(shiroSessionManager()); return securityManager; } /** * @Description 自定义RealmImpl */ @Bean(name="shiroDbRealm") public ShiroDbRealm shiroDbRealm(){ return new ShiroDbRealmImpl(); } /** * @Description 会话管理器 */ @Bean(name="sessionManager") public DefaultWebSessionManager shiroSessionManager(){ DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); sessionManager.setSessionValidationSchedulerEnabled(false); sessionManager.setSessionIdCookieEnabled(true); sessionManager.setSessionIdCookie(simpleCookie()); sessionManager.setGlobalSessionTimeout(3600000); return sessionManager; } /** * @Description 保证实现了Shiro内部lifecycle函数的bean执行 */ @Bean(name = "lifecycleBeanPostProcessor") public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * @Description AOP式方法级权限检查 */ @Bean @DependsOn("lifecycleBeanPostProcessor") public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); return defaultAdvisorAutoProxyCreator; } /** * @Description 配合DefaultAdvisorAutoProxyCreator事项注解权限校验 */ @Bean public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() { AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor(); aasa.setSecurityManager(defaultWebSecurityManager()); return new AuthorizationAttributeSourceAdvisor(); } /** * @Description 过滤器链 */ private Map filterChainDefinition(){ List list = PropertiesUtil.propertiesShiro.getKeyList(); Map map = new LinkedHashMap<>(); for (Object object : list) { String key = object.toString(); String value = PropertiesUtil.getShiroValue(key); log.info("读取防止盗链控制:---key{},---value:{}",key,value); map.put(key, value); } return map; } /** * @Description 自定义过滤器定义 */ private Map filters() { Map map = new HashMap(); map.put("roleOr", new RolesOrAuthorizationFilter()); return map; } /** * @Description Shiro过滤器 */ @Bean("shiroFilter") public ShiroFilterFactoryBean shiroFilterFactoryBean(){ ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); shiroFilter.setSecurityManager(defaultWebSecurityManager()); //使自定义过滤器生效 shiroFilter.setFilters(filters()); shiroFilter.setFilterChainDefinitionMap(filterChainDefinition()); shiroFilter.setLoginUrl("/login"); shiroFilter.setUnauthorizedUrl("/login"); return shiroFilter; }}
4、缓存对象SimpleMapCache
package com.itheima.shiro.core.base;import com.itheima.shiro.utils.EmptyUtil;import org.apache.shiro.cache.Cache;import org.apache.shiro.cache.CacheException;import java.io.Serializable;import java.util.Collection;import java.util.Collections;import java.util.Map;import java.util.Set;/** * @Description 缓存实现类, 实现序列 接口方便对象存储于第三方容器(Map存放键值对) */public class SimpleMapCache implements Cache, Serializable { private final Map attributes; private final String name; public SimpleMapCache(String name, Map backingMap) { if (name == null) throw new IllegalArgumentException("Cache name cannot be null."); if (backingMap == null) { throw new IllegalArgumentException("Backing map cannot be null."); } else { this.name = name; attributes = backingMap; } } public Object get(Object key) throws CacheException { return attributes.get(key); } public Object put(Object key, Object value) throws CacheException { return attributes.put(key, value); } public Object remove(Object key) throws CacheException { return attributes.remove(key); } public void clear() throws CacheException { attributes.clear(); } public int size() { return attributes.size(); } public Set keys() { Set keys = attributes.keySet(); if (!keys.isEmpty()) return Collections.unmodifiableSet(keys); else return Collections.emptySet(); } public Collection values() { Collection values = attributes.values(); if (!EmptyUtil.isNullOrEmpty(values)) return Collections.unmodifiableCollection(values); else return Collections.emptySet(); } @Override public String toString() { return "SimpleMapCache [attributes=" + attributes + ", name=" + name + ", keys()=" + keys() + ", size()=" + size() + ", values()=" + values() + "]"; }}
5、ShiroRedissionSerialize序列化工具
package com.itheima.shiro.utils;import lombok.extern.log4j.Log4j2;import org.apache.shiro.codec.Base64;import java.io.*;/** * @Description:实现shiro会话的序列化存储 */@Log4j2public class ShiroRedissionSerialize { public static Object deserialize(String str) { if (EmptyUtil.isNullOrEmpty(str)) { return null; } ByteArrayInputStream bis = null; ObjectInputStream ois = null; Object object=null; try { bis = new ByteArrayInputStream(EncodesUtil.decodeBase64(str)); ois = new ObjectInputStream(bis); object = ois.readObject(); } catch (IOException |ClassNotFoundException e) { log.error("流读取异常:{}",e); } finally { try { bis.close(); ois.close(); } catch (IOException e) { log.error("流读取异常:{}",e); } } return object; } public static String serialize(Object obj) { if (EmptyUtil.isNullOrEmpty(obj)) { return null; } ByteArrayOutputStream bos = null; ObjectOutputStream oos = null; String base64String = null; try { bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); oos.writeObject(obj); base64String = EncodesUtil.encodeBase64(bos.toByteArray()); } catch (IOException e) { log.error("流写入异常:{}",e); } finally { try { bos.close(); oos.close(); } catch (IOException e) { log.error("流写入异常:{}",e); } } return base64String; }}
6、缓存服务接口SimpleCacheService
SimpleCacheService
package com.itheima.shiro.core;import org.apache.shiro.cache.Cache;import org.apache.shiro.cache.CacheException;/** * @Description 简单的缓存管理接口 */public interface SimpleCacheService { /** * 功能说明::新增缓存堆到管理器 */ void createCache(String cacheName, Cache cache) throws CacheException; /** * 方法名::getCache * 功能说明::获取缓存堆 */ Cache getCache(String cacheName) throws CacheException; /** * 方法名::removeCache * 功能说明::移除缓存堆 */ void removeCache(String cacheName) throws CacheException; /** * 方法名::updateCahce * 功能说明::更新缓存堆 */ void updateCahce(String cacheName, Cache cache) throws CacheException;}
SimpleCacheServiceImpl
调用RedissonClient去实现缓存,同时使用ShiroRedissionSerialize实现序列化
package com.itheima.shiro.core.impl;import com.itheima.shiro.constant.CacheConstant;import com.itheima.shiro.core.SimpleCacheService;import com.itheima.shiro.utils.ShiroRedissionSerialize;import lombok.extern.log4j.Log4j2;import org.apache.shiro.SecurityUtils;import org.apache.shiro.cache.Cache;import org.apache.shiro.cache.CacheException;import org.redisson.api.RBucket;import org.redisson.api.RedissonClient;import org.springframework.stereotype.Component;import javax.annotation.Resource;import java.util.concurrent.TimeUnit;/** * * @Description 简单的缓存管理接口的实现 */@Log4j2@Componentpublic class SimpleCacheServiceImpl implements SimpleCacheService { @Resource(name = "redissonClientForShiro") RedissonClient redissonClient; @Override public void createCache(String name, Cache cache){ RBucket bucket = redissonClient.getBucket(CacheConstant.GROUP_CAS+name); bucket.trySet(ShiroRedissionSerialize.serialize(cache), SecurityUtils.getSubject().getSession().getTimeout()/1000, TimeUnit.SECONDS); } @SuppressWarnings("unchecked") @Override public Cache getCache(String name) throws CacheException { RBucket bucket = redissonClient.getBucket(CacheConstant.GROUP_CAS+name); return (Cache) ShiroRedissionSerialize.deserialize(bucket.get()); } @Override public void removeCache(String name) throws CacheException { RBucket bucket = redissonClient.getBucket(CacheConstant.GROUP_CAS+name); bucket.delete(); } @Override public void updateCahce(String name, Cache cache){ RBucket bucket = redissonClient.getBucket(CacheConstant.GROUP_CAS+name); bucket.set(ShiroRedissionSerialize.serialize(cache), SecurityUtils.getSubject().getSession().getTimeout()/1000, TimeUnit.MILLISECONDS); }}
shiro原理_java:shiro高级篇——1相关推荐
- java shiro原理_Springboot shiro认证授权实现原理及实例
关于认证授权,需要的数据表有:用户表,角色表,用户角色关联表,权限表,角色权限关联表,一次如下 之前写过了shiro的登录认证,在自定义的realm中,我们实现AuthorizingRealm接口中的 ...
- java http 面试题_Java面试高级篇—说说TCP,UDP和socket,Http之间联系和区别面试题12期...
TCP协议 TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义.在简化的计算机网络O ...
- 黑马程序员_java高级篇网络编程TCP实战Day8(上)
---------------------ASP.Net+Android+IOS开发.Net培训.期待与您交流! ----------- 黑马程序员_java高级篇网络编程TCP实战Day8(上) ( ...
- DataTable 深入解析数据源绑定原理之高级篇
前言 在上篇写了篇 实战系列之天气预报实时采集 ,有个别同志认为没技术含量,也许正如所说. 只是人各有看法,当我写出一篇文章时,我只是希望: 1:如果你还不懂,请看写法,了解想法 2:如果你已懂,略过 ...
- 一起谈.NET技术,DataTable 深入解析数据源绑定原理之高级篇
前言 在上篇写了篇 实战系列之天气预报实时采集 ,有个别同志认为没技术含量,也许正如所说. 只是人各有看法,当我写出一篇文章时,我只是希望: 1:如果你还不懂,请看写法,了解想法. 2:如果你已懂,略 ...
- Shiro(一)之shiro简介与工作原理
一.shiro简介 这里我先来介绍一下什么是shiro,Apache Shiro 是 Java 的一个安全框架.目前,使用 Apache Shiro 的人越来越多,因为它相当简单,对比 Spring ...
- 安全认证框架Shiro (二)- shiro过滤器工作原理
安全认证框架Shiro (二)- shiro过滤器工作原理 安全认证框架Shiro 二- shiro过滤器工作原理 第一前言 第二ShiroFilterFactoryBean入口 第三请求到来解析过程 ...
- Sqlserver 高级篇 聚集索引原理
原理 Sqlserver 高级篇 非聚集索引原理 说完非聚集索引 接着说 聚集索引 聚集索引就是把数据按照 用户设置排好顺序 与非聚集索引不同 非聚集索引不会动数据页 只会新增一个索引表 聚集索引直 ...
- java ee 6 源码_Java EE 6开发手册·高级篇(第4版)
资源名称:Java EE 6开发手册·高级篇(第4版) 内容简介: <Java EE 6 开发手册?高级篇(第4 版)>是一本面向实战.以示例为驱动.在Java 平台企业版6(Java E ...
最新文章
- 网络编程中的关键问题总结
- 一道有意思的找规律题目 --- CodeForces - 964A
- ssh反向主动连接 及脚本加密
- ZooKeeper 如何保证数据一致性
- duilib bkimage 属性
- P4180-[BJWC2010]严格次小生成树【Kruskal,倍增】
- react中的状态机_在基于状态图的状态机上使用React的模式
- 转://Linux Multipath多路径配置与使用案例
- 中科慧眼双目安装pcl
- 基于Tezos构建的DEX Dexter被曝合约存在漏洞,开发团队Nomadic Labs已重写合约
- Android 开机自启动
- 《剑指offer》面试题34——丑数
- System Center App Controller 2012 Service Pack 1系列文章
- 开源推荐:表单收集系统-TDuck填鸭 v2版本!
- 10分钟教你用python做个打飞机(超详细超入门教程)附源代码下载
- LCD高抗干扰液晶段码屏显示驱动芯片:VK2C21A/B/BA/C/D 大量应用于音箱/音响面板LCD显示驱动
- 爬取虎扑社区-晒晒照片
- Cobar的架构与实践
- 酒店管理系统功能结构图
- 【verbs】ibv_req_notify_cq()
热门文章
- 【Java】5.3 成员变量和局部变量
- 有了 for (;;) 为什么还需要 while (true) ? 到底哪个更快?
- Mybatis一级缓存,二级缓存的实现就是这么简单
- 并发基础篇(一) 线程介绍
- 信息系统项目管理知识--项目范围管理
- method initializationerror not found:JUnit4单元测试报错问题
- html fond 怎么居中,BeautifulSoup标签定位方法总结
- E: 您必须在 sources.list 中指定代码源(deb-src) URI 解决办法
- Sharding-JDBC改写自己查询规则思路
- MySQL多表查询核心优化