Shiro功能应用--Shiro集成RedisTemplate(SDR)

Posted 做猪呢,最重要的是开森啦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shiro功能应用--Shiro集成RedisTemplate(SDR)相关的知识,希望对你有一定的参考价值。

文章目录

     上一篇文章Shiro功能应用(七)–Shiro集成Redis缓存(shiro-redis3.1.0)中提到,继承shiro-redis,授权的User实体类要有AuthCacheKey或者Id属性,这有一定局限性,本文在上一篇文章代码基础上,修改成集成SDR(spring-boot-starter-data-redis依赖)

代码实现:

      代码地址:
          https://github.com/OooooOz/SpringBoot-Shiro

     自定义缓存处理器
     继承CacheManager,重写getCache方法,方法返回自定义缓存类(实现cache接口,重写get、remove等方法)。
     hashKey()方法对获取缓存做兼容,shiro缓存中获取认证if的key是username,而缓存获取权限info的key是user对象,所以做个区分。

//redis缓存实现类
package com.demo.config;

import java.util.Collection;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import com.demo.entity.User;


@Component
public class RedisCacheManager implements CacheManager 

    private String cacheKeyPrefix = "shiro:";

    @Autowired 
    private StringRedisTemplate redisTemplate;

    @Override
    public <K, V> Cache<K, V> getCache(String name) throws CacheException 
        return new ShiroRedisCache<K,V>(cacheKeyPrefix+name);
    

    /**
     * 为shiro量身定做的一个redis cache,为Authorization cache做了特别优化
     */
    public class ShiroRedisCache<K, V> implements Cache<K, V> 

        private String cacheKey;

        public ShiroRedisCache(String cacheKey) 
            this.cacheKey=cacheKey;
        

        @Override
        public V get(K key) throws CacheException 
            BoundHashOperations<String,K,V> hash = redisTemplate.boundHashOps(cacheKey);
            Object k=hashKey(key);
            V v = hash.get(k);
            return v;
        

        @Override
        public V put(K key, V value) throws CacheException 
            BoundHashOperations<String,K,V> hash = redisTemplate.boundHashOps(cacheKey);
            Object k=hashKey(key);
            hash.put((K)k, value);
            return value;
        

        @Override
        public V remove(K key) throws CacheException 
            BoundHashOperations<String,K,V> hash = redisTemplate.boundHashOps(cacheKey);
            Object k=hashKey(key);
            V value=hash.get(k);
            hash.delete(k);
            return value;
        

        @Override
        public void clear() throws CacheException 
            redisTemplate.delete(cacheKey);
        

        @Override
        public int size() 
            BoundHashOperations<String,K,V> hash = redisTemplate.boundHashOps(cacheKey);
            return hash.size().intValue();
        

        @Override
        public Set<K> keys() 
            BoundHashOperations<String,K,V> hash = redisTemplate.boundHashOps(cacheKey);
            return hash.keys();
        

        @Override
        public Collection<V> values() 
            BoundHashOperations<String,K,V> hash = redisTemplate.boundHashOps(cacheKey);
            return hash.values();
        

        protected Object hashKey(K key) 
        	//此处很重要,如果key是登录凭证,那么这是访问用户的授权缓存;将登录凭证转为user对象,
        	//返回user的name属性做为hash key,否则会以user对象做为hash key,这样就不好清除指定用户的缓存了
            if(key instanceof PrincipalCollection) 
                PrincipalCollection pc=(PrincipalCollection) key;
                User user =(User)pc.getPrimaryPrincipal();
                return user.getUserName();
            else if (key instanceof User) 
            	User user =(User) key;
            	return user.getUserName();
			
            return key;
        
    



     ShiroConfig的注入自定义缓存管理器*以及redisTemplate

  /**
     *  注入redisTemplate工具
     * */
    @Bean
    public StringRedisTemplate redisTemplate(JedisConnectionFactory jedisConnectionFactory)
        StringRedisTemplate redisTemplate = new StringRedisTemplate(jedisConnectionFactory);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();

        redisTemplate.setKeySerializer(stringRedisSerializer);              //键值序列化方式
        redisTemplate.setValueSerializer(jdkSerializationRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);          //绑定hash的序列化方式
        redisTemplate.setHashValueSerializer(jdkSerializationRedisSerializer);
//		redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return redisTemplate;

    
    /**
     *  Jedis连接工厂,Springboot2.0以上采用redisStandaloneConfiguration
     * */
    @Bean
    public JedisConnectionFactory jedisConnectionFactory(RedisStandaloneConfiguration redisStandaloneConfiguration)
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration);
        return jedisConnectionFactory;
    

    //JedisConnectionFactory注入的redis配置
    @Bean
    public RedisStandaloneConfiguration redisStandaloneConfiguration()
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName("192.168.2.104");
        redisStandaloneConfiguration.setPort(6379);
        //redisStandaloneConfiguration.setPassword(RedisPassword);
        return redisStandaloneConfiguration;
    

    /**
     *  自定义封装的redis缓存操作类
     * */
    @Bean("redisCacheManager")
    public RedisCacheManager redisCacheManager()
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        return redisCacheManager;
    

     KickOut过滤器修改:
     之前EHCache缓存时,队列可以先放缓存,再往缓存的队列push值。险种Redis做缓存,需要先将sessionId值放入队列,队列再放入缓存:

功能测试:

     打开两个浏览器登录,会有一个被踢出来,集成完毕。从RDM里可以看到redis缓存。

以上是关于Shiro功能应用--Shiro集成RedisTemplate(SDR)的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot11:集成Shiro

SpringBoot11:集成Shiro

springboot集成shiro实现用户登录认证

Shiro - Shiro简介;Shiro与Spring Security区别;Spring Boot集成Shiro

springmvc集成shiro登录失败处理

SpringBoot集成Apache Shiro