Shiro use Session Cache

Shiro's Session caches are mainly two schemes, one is using Session Shiro own, without using the HttpSession, Shiro's own implementation and Session caching Cache interface; the other is the direct use of spring boot spring-session-data-redispackage and configured and RedisTemplate Redis sequence of the method can be used. The second method is relatively simple, first needs a lot of development work. Here is the main idea of the first way.

Shiro cache

To cache Session, the best first integrated Shiro cache. Shiro offers a similar Spring's Cache abstract, that Shiro itself does not implement Cache, but Cache conducted and abstract, facilitate the replacement of different underlying Cache implementation. Shiro provides CacheManager Cache interface and interfaces, as well as interfaces to inject CacheManagerAware CacheManager.

  • Realization of Cache cache interface, shiro's Spring Cache Cache to be packed
@SuppressWarnings("unchecked")
class SpringCacheWrapper <V> implements Cache<String, V> {

    private final String REDIS_SHIRO_CACHE = "shiro-cache#";
    private org.springframework.cache.Cache springCache;
    private CacheManager cacheManager;

    SpringCacheWrapper(CacheManager cacheManager, @NotNull org.springframework.cache.Cache springCache) {
        this.springCache = springCache;
        this.cacheManager = cacheManager;
    }

    @Override
    public V get(String key) throws CacheException {
        ValueWrapper cacheValue = springCache.get(getCacheKey(key));            
        return (V) Optional.ofNullable(cacheValue).map(p->p.get()).orElse(null);
    }

    @Override
    public V put(String key, V value) throws CacheException {
        springCache.put(getCacheKey(key), value);
        return value;
    }

    @Override
    public V remove(String key) throws CacheException {
        springCache.evict(getCacheKey(key));
        return null;
    }

    private String getCacheKey(String key) {
        return REDIS_SHIRO_CACHE + key;
    }

    @Override
    public void clear() throws CacheException {
        springCache.clear();
    }

    @Override
    public int size() {
        throw new UnsupportedOperationException("invoke spring cache size method not supported");
    }

    @Override
    public Set<String> () {
        throw new UnsupportedOperationException("invoke spring cache keys method not supported");
    }

    @Override
    public Collection<V> values() {
        throw new UnsupportedOperationException("invoke spring cache values method not supported");
    }
}

CacheManager achieve the cache interface, shiro of CacheManager packaging conduct of Spring CacheManager

public class SpringCacheManagerWrapper implements CacheManager {

    private org.springframework.cache.CacheManager cacheManager;
    
    public SpringCacheManagerWrapper(org.springframework.cache.CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    @Override
    public <K, V> Cache<K, V> getCache(String name) throws CacheException {
        org.springframework.cache.Cache springCache = cacheManager.getCache(name);
        return new SpringCacheWrapper(springCache);     
    }
}

Session cache

The need to achieve CacheSessionDAO interface, Session caching method.

public class ShiroSessionDAO extends CachingSessionDAO {

    private Cache<String, Session> cache;

    public ShiroSessionDAO(CacheManager cacheManager) {
        String cacheName = getActiveSessionsCacheName();
        this.setCacheManager(cacheManager);
        this.cache = getCacheManager().getCache(cacheName);
    }

    @Override
    protected void doUpdate(Session session) {
        if(session==null) {
            return;
        }
        cache.put(session.getId().toString(), session);
    }

    @Override
    protected void doDelete(Session session) {
        if(session==null){
            return;
        }       
        cache.remove(session.getId().toString());
    }

    @Override
    protected Serializable doCreate(Session session) {
        if(session == null) {
            return null;
        }      
        Serializable sessionId = this.generateSessionId(session);
        assignSessionId(session, sessionId);
        cache.put(sessionId.toString(), session);
        return sessionId;
    }


    @Override
    protected Session doReadSession(Serializable sessionId) {
        if(sessionId==null) {
            return null;            
        }
        
        Session session=(Session) cache.get(sessionId.toString());
        return session;
    }
}

Configuration Bean

Configuration Redis

@Configuration  
public class RedisConfiguration extends CachingConfigurerSupport {

    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append("#" + method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Bean
    public RedisCacheManager redisCacheManager(@Autowired RedisTemplate redisTemplate) {
        // spring cache注解序列化配置
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .serializeKeysWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getKeySerializer()))
                .serializeValuesWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()))
                .disableCachingNullValues()
                .entryTtl(Duration.ofSeconds(60));

        Set<String> cacheNames = new HashSet<>();
        cacheNames.add("user");

        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
        configMap.put("user", redisCacheConfiguration.entryTtl(Duration.ofSeconds(120)));

        RedisCacheManager redisCacheManager = RedisCacheManager.builder(redisTemplate.getConnectionFactory())
                .cacheDefaults(redisCacheConfiguration).transactionAware().initialCacheNames(cacheNames) 
                .withInitialCacheConfigurations(configMap).build();
        return redisCacheManager;
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(@Autowired RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<Object, Object>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer); // key序列化
        redisTemplate.setHashKeySerializer(stringSerializer); // Hash key序列化
        
        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<Object>(Object.class);
        redisTemplate.setValueSerializer(fastJsonRedisSerializer); // value序列化
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); // Hash value序列化
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
    
    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

}

Shiro cache configuration and CacheSessionDao

@Bean(name = "securityManager")
public org.apache.shiro.mgt.SecurityManager defaultWebSecurityManager(@Autowired UserRealm      userRealm, @Autowired TokenRealm tokenValidateRealm) {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setAuthenticator(multiRealmAuthenticator());
    securityManager.setRealms(Arrays.asList(userRealm, tokenValidateRealm));
    securityManager.setRememberMeManager(rememberMeManager());
    securityManager.setCacheManager(new SpringCacheManagerWrapper());
    //必须使用DefaultWebSessionManager,不能是ServletContainerSessionManager
    DefaultWebSessionManager webSessionManager = new DefaultWebSessionManager();
    webSessionManager.setSessionDAO(cachingSessionDAO);
    securityManager.setSessionManager(webSessionManager);
    return securityManager;
}

to sum up

It can be seen from the above configuration Shiro Session caching step, it is quite troublesome. In this manner would have been intended, there was later found in the online Session Redis integrated package, as shown below, also found in this manner is simpler to use, then directly use Spring Session, and only need to configure Redis (as shown in FIG. ) on it.

 <dependency>
     <groupId>org.springframework.session</groupId>
     <artifactId>spring-session-data-redis</artifactId>
</dependency>

Guess you like

Origin www.cnblogs.com/fzsyw/p/11531692.html