zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    图书-哲学-奥卡姆剃刀:《奥卡姆剃刀原理》
    汉语-词语-认知:认知能力
    汉语-词语-认知:认知水平
    汉语-词语:认知
    pg_dump
    pg_ctl
    pg_controldata
    pg_config
    paste
    passwd
  • 原文地址:https://www.cnblogs.com/itjiangpo/p/14181341.html
Copyright © 2011-2022 走看看