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

  • 相关阅读:
    codevs 2632 非常好友
    codevs 1213 解的个数
    codevs 2751 军训分批
    codevs 1519 过路费
    codevs 1503 愚蠢的宠物
    codevs 2639 约会计划
    codevs 3369 膜拜
    codevs 3135 River Hopscotch
    数论模板
    JXOJ 9.7 NOIP 放松模拟赛 总结
  • 原文地址:https://www.cnblogs.com/dataoblogs/p/14121884.html
Copyright © 2011-2022 走看看