• SpringBoot 集成Shiro之使用Redis缓存授权认证信息


    因为用户认证与授权需要从数据库中查询并验证信息,但是对于权限很少改变的情况,这样不断从数据库中查询角色验证权限,对整个系统的开销很大,对数据库压力也随之增大。因此可以将用户认证和授权信息都缓存起来,第一次缓存没有的时候会自动从数据库中获取,并添加到缓存中;如果缓存中已经有该登录用户的认证和权限信息就直接从缓存中拿

    使用CacheManager

    Cache的作用

    • 用来减轻数据库的访问压力,从而提升查询效率。

    • 流程

      image-20200817171818715

    使用默认的EhCache实现缓存

    1、引入Ehcache相关依赖

    <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache -->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-ehcache</artifactId>
        <version>1.4.0</version>
    </dependency>
    
    

    2、开启缓存

    在ShiroConfig配置类中,找到注入的Realm方法,开启缓存

     @Bean
        public Realm getRealm() {
            CustomRelam customRelam = new CustomRelam();
            // 创建校验匹配器
            HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
            // 散列1024次
            hashedCredentialsMatcher.setHashIterations(1024);
            // 加密算法是MD5
            hashedCredentialsMatcher.setHashAlgorithmName("md5");
            customRelam.setCredentialsMatcher(hashedCredentialsMatcher);
    
            // 开启全局缓存
            customRelam.setCachingEnabled(true);
            // 开启认证缓存
            customRelam.setAuthenticationCachingEnabled(true);
            // 设置认证缓存管理的名字
            customRelam.setAuthenticationCacheName("authenticationCache");
            // 开启授权缓存管理
            customRelam.setAuthorizationCachingEnabled(true);
            // 设置授权缓存管理的名字
            customRelam.setAuthorizationCacheName("authorizationCache");
            // 开启缓存
            customRelam.setCacheManager(new EhCacheManager());
    
            return customRelam;
        }
    

    开启缓存后第一次认证与授权需要查询数据库,以后再不修改用户权限或者密码的情况下都是从缓存中取出数据。

    Shiro使用Redis做缓存

    1、引入相关依赖

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
        <version>2.3.2.RELEASE</version>
    </dependency>
    
    

    2、配置redis连接

    spring.redis.database=0
    spring.redis.port=6379
    spring.redis.host=127.0.0.1
    # 链接超时时间 单位 ms(毫秒)
    spring.redis.timeout=3000
    ################ Redis 线程池设置 ##############
    # 连接池最大连接数(使用负值表示没有限制) 默认 8
    spring.redis.jedis.pool.max-active=8
    # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
    spring.redis.jedis.pool.max-wait=-1
    # 连接池中的最大空闲连接 默认 8
    spring.redis.jedis.pool.max-idle=8
    # 连接池中的最小空闲连接 默认 0
    spring.redis.jedis.pool.min-idle=0
    
    

    3、启动redis服务

    Windows下进入redis目录,先启动redis-server.exe,然后启动redis-cli.exe

    进入命令行

    image-20200817222604924

    然后在cache包下创建RedisCacheManager实现CacheManager接口

    public class RedisCacheManager implements CacheManager {
        @Override
        public <K, V> Cache<K, V> getCache(String cacheKey) throws CacheException {
            return new RedisCache<>(cacheKey);
        }
    }
    

    创建RedisCache实现Cache接口

    public class RedisCache<K, V> implements Cache<K, V> {
        private String cacheName;
    
        public RedisCache() {
        }
    
        public RedisCache(String cacheName) {
            this.cacheName = cacheName;
        }
    
    
        private RedisTemplate getRedisTemplate() {
            RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtil.getBean("redisTemplate");
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
            return redisTemplate;
        }
    
        @Override
        public V get(K k) throws CacheException {
    
            return (V) getRedisTemplate().opsForHash().get(this.cacheName,k.toString());
    
        }
    
        @Override
        public V put(K k, V v) throws CacheException {
    
            getRedisTemplate().opsForHash().put(this.cacheName,k.toString(), v);
            return null;
        }
    
         @Override
        public V remove(K k) throws CacheException {
    
            return (V) getRedisTemplate().opsForHash().delete(this.cacheName,k.toString());
        }
    
        @Override
        public void clear() throws CacheException {
            getRedisTemplate().opsForHash().delete(this.cacheName);
        }
    
        @Override
        public int size() {
            return getRedisTemplate().opsForHash().size(this.cacheName).intValue();
        }
    
        @Override
        public Set<K> keys() {
            return getRedisTemplate().opsForHash().keys(this.cacheName);
        }
    
        @Override
        public Collection<V> values() {
            return getRedisTemplate().opsForHash().values(this.cacheName);
        }
    }
    

    由于自定义realm中认证所需要的盐值内部并没有实现序列化接口,所以我们需要自己定一个MyByteSource继承SimpleByteSource并实现Serializable接口

    import org.apache.shiro.util.SimpleByteSource;
    
    import java.io.Serializable;
    
    public class MyByteSource extends SimpleByteSource implements Serializable {
        public MyByteSource(String string) {
            super(string);
        }
    }
    

    在自定义的Realm中需要在认证的方法中,改写salt的处理。

    image-20200817223254188

    • 注意实体类(角色类,用户类,权限类)要记得实现Serializable接口

      最后在Shiro配置类中开启缓存,使用我们自己定义的RedisManager

       @Bean
          public Realm getRealm() {
              CustomRelam customRelam = new CustomRelam();
              // 创建校验匹配器
              HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
              // 散列1024次
              hashedCredentialsMatcher.setHashIterations(1024);
              // 加密算法是MD5
              hashedCredentialsMatcher.setHashAlgorithmName("md5");
              customRelam.setCredentialsMatcher(hashedCredentialsMatcher);
      
              // 开启全局缓存
              customRelam.setCachingEnabled(true);
              // 开启认证缓存
              customRelam.setAuthenticationCachingEnabled(true);
              // 设置认证缓存管理的名字
              customRelam.setAuthenticationCacheName("authenticationCache");
              // 开启授权缓存管理
              customRelam.setAuthorizationCachingEnabled(true);
              // 设置授权缓存管理的名字
              customRelam.setAuthorizationCacheName("authorizationCache");
              // 开启Redis缓存
              customRelam.setCacheManager(new RedisCacheManager());
      
              return customRelam;
          }
      

      启动项目,登录用户,第一次会从数据库中查询,并通过RedisTemplate的put方法将用户信息装入缓存,下次再刷新首页就会从redis中查询权限,授权等信息。退出时会调用RedisTemplate中的remove方法清除向对应的用户缓存。

      image-20200817223929129

    image-20200817223959338

  • 相关阅读:
    keycloak~管理平台的查询bug与自定rest中文检索
    gRPC四种模式、认证和授权,C#实战演示
    asp.net core 集成JWT
    从不同使用场景来介绍git的基础命令
    用scikit-learn进行LDA降维——以前没有注意,原来LDA降维竟然这么好用!对无监督的任务使用PCA进行降维,对有监督的则应用LDA。
    ID3/Cart/C4.5区别
    超参数调优——google Vizier采用迁移学习的思想,主要是从之前调参的经验中学习,为新算法提出最佳超参数
    sklearn 绘制roc曲线
    原来ROC曲线更加健壮地反映模型的效果,看来还是比较关键的(就像逻辑回归,你总是希望模型让0/1分类的数据尽可能都向两端靠对不对,ROC就是反映这个好坏的指标)
    word2vec的原理——根据单词的上下文去预测单词出现,然后让整体的概率最大化。学习这样一个神经网络,然后选择隐藏作为vector表示。最初单词是onehot编码!
  • 原文地址:https://www.cnblogs.com/dataoblogs/p/14121884.html
Copyright © 2020-2023  润新知