欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > Shiro学习(五):Shiro对权限的缓存

Shiro学习(五):Shiro对权限的缓存

2025/4/5 9:42:18 来源:https://blog.csdn.net/liang8999/article/details/146996054  浏览:    关键词:Shiro学习(五):Shiro对权限的缓存

一、问题描述

       由前边的学习中了解,用户的角色权限一般存储在数据库中,每次进行权限校验时都要从

       数据库查询用户的角色权限信息;对数据库来说这样频繁的查询压力太大了,也影响程序的

       性能。

       Shiro 中执行权限角色校验时,默认也是优先从缓存中查询用户权限信息,若缓存中查询不到

       用户信息,然后才去数据库中查询用户信息。

       前边笔记(三)RolesAuthorizationFilter 分析中,AuthorizingRealm.getAuthorizationInfo 方

       法中先执行 getAvailableAuthorizationCache() 方法从缓存中查询对应信息,如下图所示:

               

       

二、基于JVM内存的权限缓存

       Shiro 中虽然默认提供了基于JVM内存的缓存机制,但是默认是没开启,权限角色信息并不会

       缓存;因为默认情况下 DefaultWebSecurityManager 中 CacheManager 为null,

       如下图所示:

             

      shiro 默认提供的jvm缓存是 MemoryConstrainedCacheManager,它是把权限角色信息缓存到

     Map 中,如下所示:

              

              

       1、如何开启Shiro 缓存

            开启 Shiro 缓存功能也很简单,只要把 MemoryConstrainedCacheManager 注入到 

            DefaultWebSecurityManager 中就行了,示例代码如下:

    @Beanpublic DefaultWebSecurityManager securityManager(CustomRealm realm, SessionManager sessionManager ){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);//将使用的SessionManager注入到SecurityManagersecurityManager.setSessionManager(sessionManager);//使用Shiro 提供的基于JVM 内存的 CacheManagerMemoryConstrainedCacheManager cacheManager = new MemoryConstrainedCacheManager();securityManager.setCacheManager(cacheManager);return securityManager;}

三、基于Redis的权限缓存

       将权限信息存储到内存中在实际工作用有很多限制,如:占用内存资源、只适用于单机环境

       、缓存周期短等等。

       在实际工作中一般将权限信息存储到中间件Redis 中,实现步骤如下:

       1)模仿 MapCache 定义 RedisCache 用于将数据保存到Redis 中,有一点要注意,

             RedisCache需要实现 org.apache.shiro.cache 包下的接口 Cache,

             示例代码如下:

@Component
public class RedisCache<K,V> implements Cache<K,V> {@Autowiredprivate RedisTemplate redisTemplate;private final String CACHE_PREFIX = "cache:";/*** 获取授权缓存信息* @param k* @return* @throws CacheException*/@Overridepublic V get(K k) throws CacheException {System.out.println("从redis 查询权限信息~~~~~~~~~~~");V v = (V) redisTemplate.opsForValue().get(CACHE_PREFIX + k);if(v != null){redisTemplate.expire(CACHE_PREFIX + k,15, TimeUnit.MINUTES);}return v;}/*** 存放缓存信息* @param k* @param v* @return* @throws CacheException*/@Overridepublic V put(K k, V v) throws CacheException {redisTemplate.opsForValue().set(CACHE_PREFIX + k,v,15,TimeUnit.MINUTES);return v;}/*** 清空当前缓存* @param k* @return* @throws CacheException*/@Overridepublic V remove(K k) throws CacheException {V v = (V) redisTemplate.opsForValue().get(CACHE_PREFIX + k);if(v != null){redisTemplate.delete(CACHE_PREFIX + k);}return v;}/*** 清空全部的授权缓存* @throws CacheException*/@Overridepublic void clear() throws CacheException {Set keys = redisTemplate.keys(CACHE_PREFIX + "*");redisTemplate.delete(keys);}/*** 查看有多个权限缓存信息* @return*/@Overridepublic int size() {Set keys = redisTemplate.keys(CACHE_PREFIX + "*");return keys.size();}/*** 获取全部缓存信息的key* @return*/@Overridepublic Set<K> keys() {Set keys = redisTemplate.keys(CACHE_PREFIX + "*");return keys;}/*** 获取全部缓存信息的value* @return*/@Overridepublic Collection<V> values() {Set values = new HashSet();Set keys = redisTemplate.keys(CACHE_PREFIX + "*");for (Object key : keys) {Object value = redisTemplate.opsForValue().get(key);values.add(value);}return values;}
}

       2)模仿 MemoryConstrainedCacheManager 定义 RedisCacheManager;

             RedisCacheManager 实现 org.apache.shiro.cache 包下的接口,并重写 getCache 方法

             示例代码如下:

@Component
public class RedisCacheManager implements CacheManager {@Autowiredprivate RedisCache redisCache;/*** 返回 Cache 的实现类* @param s* @return* @param <K>* @param <V>* @throws CacheException*/@Overridepublic <K, V> Cache<K, V> getCache(String s) throws CacheException {return redisCache;}
}

      3)将自定义的 RedisCacheManager 注入到  DefaultWebSecurityManager 中;

           示例代码如下:

 @Beanpublic DefaultWebSecurityManager securityManager(CustomRealm realm, SessionManager sessionManager, RedisCacheManager cacheManager){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);//将使用的SessionManager注入到SecurityManagersecurityManager.setSessionManager(sessionManager);//使用自定义基于Redis 缓存的 RedisCacheManagersecurityManager.setCacheManager(cacheManager);return securityManager;}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词