• SpringBoot2(十二)当Shiro遇上RedisCache


    ShiroCache重点在于配置SecurityManager,关键配置只有下面两个,SessionManager和CacheManager ,其中SessionManager 可以全部默认,无须设计,

    重点在 CacheManager 上,CacheManager 需要实现CacheManager接口和Cache接口。

    securityManager.setSessionManager(SessionManager sessionManager);
    securityManager.setCacheManager(CacheManager cacheManager) ;

    SecurityManager 与 AuthorizingRealm 相关,配置中找到 AuthorizingRealm 实现类,即可找到 SecurityManager 

      /**
       * 安全管理器
       */
      @Bean
      public SecurityManager securityManager(RedisTemplate<String, Object> redisTemplate) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setCacheManager(new ShiroRedisCacheManager(redisTemplate));//需要自己实现的部分,本文内容重点
        securityManager.setRealm(new ShiroRealm());//AuthorizingRealm实现,找到你自己Shiro配置的这一行,就知道怎么添加缓存配置
        securityManager.setSessionManager(sessionManager());//代码下面已经给出,全部默认,不是当前讨论的重点
        return securityManager;
      }
    
      /**
       * session 管理对象
       */
      private DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(1800000L);
        sessionManager.setSessionDAO(new EnterpriseCacheSessionDAO());
        return sessionManager;
      }

    RedisTemplate

    Shiro默认缓存是 EhCache,因此代码上会侧重于 JDK 的序列化,因此在使用 Redis 的时候,需要实现一个采用 JDK 序列化的 RedisTemplate。
    使用JSON序列化也可以,但是需要额外的设计,这里就不多事了。

     /**
       * RedisTemplate配置--Shiro专属
       */
      @Bean
      public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        RedisSerializer<String> stringSerializer = new StringRedisSerializer();
        JdkSerializationRedisSerializer fastJsonRedisSerializer = new JdkSerializationRedisSerializer();
    
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
    
        redisTemplate.setHashKeySerializer(stringSerializer);
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
    
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
      }

    ShiroRedisCacheManager 

    import org.apache.shiro.cache.AbstractCacheManager;
    import org.apache.shiro.cache.Cache;
    import org.apache.shiro.cache.CacheException;
    import org.springframework.data.redis.core.RedisTemplate;
    
    /**
     * @author Mr.css
     * @date 2020/1/3
     */
    public class ShiroRedisCacheManager extends AbstractCacheManager {
    
      private RedisTemplate<String,Object> redisTemplate;
    
      public ShiroRedisCacheManager(RedisTemplate<String,Object> redisTemplate){
        this.redisTemplate = redisTemplate;
      }
    
      @Override
      protected Cache createCache(String name) throws CacheException {
        return new ShiroRedisCache(redisTemplate,name);
      }
    }

    ShiroRedisCache 

    这样缓存接口已经暴露出来,至于如何处理缓存,全看个人喜好

    import org.apache.shiro.cache.Cache;
    import org.apache.shiro.cache.CacheException;
    import org.apache.shiro.session.mgt.ValidatingSession;
    import org.springframework.data.redis.core.RedisTemplate;
    
    import java.util.*;
    
    /**
     * @author Mr.css
     * @date 2020/1/3
     */
    public class ShiroRedisCache implements Cache<String, ValidatingSession> {
      private RedisTemplate<String,Object> redisTemplate;
      /**
       * 前缀,用于标识哪些是Shiro的数据,前缀太长,确实会影响查询效率,可以优化
       */
      private String prefix;
    
      private String getKey(String key){
        return prefix + key;
      }
    
      ShiroRedisCache(RedisTemplate<String,Object> redisTemplate, String prefix) {
        this.redisTemplate = redisTemplate;
        this.prefix = prefix;
      }
    
      @Override
      public ValidatingSession get(String key) throws CacheException {
        if (key == null) {
          return null;
        }
        return (ValidatingSession) redisTemplate.opsForValue().get(this.getKey(key));
      }
    
      @Override
      public ValidatingSession put(String key, ValidatingSession value) throws CacheException {
        if (key == null || value == null) {
          return null;
        }
        redisTemplate.opsForValue().set(this.getKey(key), value);
        return value;
      }
    
      @Override
      public ValidatingSession remove(String key) throws CacheException {
        if (key == null) {
          return null;
        }
        key = this.getKey(key);
        ValidatingSession value = (ValidatingSession) redisTemplate.opsForValue().get(key);
        redisTemplate.delete(key);
        return value;
      }
    
      @Override
      public void clear() throws CacheException {
        redisTemplate.delete(this.keys());
      }
    
      @Override
      public int size() {
        return this.keys().size();
      }
    
      @Override
      public Set<String> keys() {
        return redisTemplate.keys(prefix + "*");
      }
    
      @Override
      public Collection<ValidatingSession> values() {
        Set<String> keys = keys();
        List<ValidatingSession> values = new ArrayList<>(keys.size());
        for (String k : keys) {
          values.add((ValidatingSession)redisTemplate.opsForValue().get(k));
        }
        return values;
      }
    }
  • 相关阅读:
    数据的追踪审计
    通知模块设计
    数据库'tempdb' 的事务日志已满处理方法
    三级联动
    组合查询
    用户控件
    MDI容器
    控件说明
    winfrom
    自动生成编号
  • 原文地址:https://www.cnblogs.com/chenss15060100790/p/12168672.html
Copyright © 2020-2023  润新知