SpringBoot2(十二)當Shiro遇上RedisCache


ShiroCache重點在於配置SecurityManager,關鍵配置只有下面兩個,SessionManager和CacheManager ,其中SessionManager 可以全部默認,無須設計,

重點在 CacheManager 上,CacheManager 需要實現CacheManager接口和Cache接口。

securityManager.setSessionManager(SessionManager sessionManager);
securityManager.setCacheManager(CacheManager cacheManager) ;

SecurityManager 與 AuthorizingRealm 相關,配置中找到 AuthorizingRealm 實現類,即可找到 SecurityManager 

  /**
   * 安全管理器
   */
  @Bean
  public SecurityManager securityManager(RedisTemplate<String, Object> redisTemplate) {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setCacheManager(new ShiroRedisCacheManager(redisTemplate));//需要自己實現的部分,本文內容重點
    securityManager.setRealm(new ShiroRealm());//AuthorizingRealm實現,找到你自己Shiro配置的這一行,就知道怎么添加緩存配置
    securityManager.setSessionManager(sessionManager());//代碼下面已經給出,全部默認,不是當前討論的重點
    return securityManager;
  }

  /**
   * session 管理對象
   */
  private DefaultWebSessionManager sessionManager() {
    DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
    sessionManager.setGlobalSessionTimeout(1800000L);
    sessionManager.setSessionDAO(new EnterpriseCacheSessionDAO());
    return sessionManager;
  }

RedisTemplate

Shiro默認緩存是 EhCache,因此代碼上會側重於 JDK 的序列化,因此在使用 Redis 的時候,需要實現一個采用 JDK 序列化的 RedisTemplate。
使用JSON序列化也可以,但是需要額外的設計,這里就不多事了。

 /**
   * RedisTemplate配置--Shiro專屬
   */
  @Bean
  public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    RedisSerializer<String> stringSerializer = new StringRedisSerializer();
    JdkSerializationRedisSerializer fastJsonRedisSerializer = new JdkSerializationRedisSerializer();

    redisTemplate.setKeySerializer(stringSerializer);
    redisTemplate.setValueSerializer(fastJsonRedisSerializer);

    redisTemplate.setHashKeySerializer(stringSerializer);
    redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);

    redisTemplate.setConnectionFactory(lettuceConnectionFactory);
    redisTemplate.afterPropertiesSet();
    return redisTemplate;
  }

ShiroRedisCacheManager 

import org.apache.shiro.cache.AbstractCacheManager;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.data.redis.core.RedisTemplate;

/**
 * @author Mr.css
 * @date 2020/1/3
 */
public class ShiroRedisCacheManager extends AbstractCacheManager {

  private RedisTemplate<String,Object> redisTemplate;

  public ShiroRedisCacheManager(RedisTemplate<String,Object> redisTemplate){
    this.redisTemplate = redisTemplate;
  }

  @Override
  protected Cache createCache(String name) throws CacheException {
    return new ShiroRedisCache(redisTemplate,name);
  }
}

ShiroRedisCache 

這樣緩存接口已經暴露出來,至於如何處理緩存,全看個人喜好

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.session.mgt.ValidatingSession;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.*;

/**
 * @author Mr.css
 * @date 2020/1/3
 */
public class ShiroRedisCache implements Cache<String, ValidatingSession> {
  private RedisTemplate<String,Object> redisTemplate;
  /**
   * 前綴,用於標識哪些是Shiro的數據,前綴太長,確實會影響查詢效率,可以優化
   */
  private String prefix;

  private String getKey(String key){
    return prefix + key;
  }

  ShiroRedisCache(RedisTemplate<String,Object> redisTemplate, String prefix) {
    this.redisTemplate = redisTemplate;
    this.prefix = prefix;
  }

  @Override
  public ValidatingSession get(String key) throws CacheException {
    if (key == null) {
      return null;
    }
    return (ValidatingSession) redisTemplate.opsForValue().get(this.getKey(key));
  }

  @Override
  public ValidatingSession put(String key, ValidatingSession value) throws CacheException {
    if (key == null || value == null) {
      return null;
    }
    redisTemplate.opsForValue().set(this.getKey(key), value);
    return value;
  }

  @Override
  public ValidatingSession remove(String key) throws CacheException {
    if (key == null) {
      return null;
    }
    key = this.getKey(key);
    ValidatingSession value = (ValidatingSession) redisTemplate.opsForValue().get(key);
    redisTemplate.delete(key);
    return value;
  }

  @Override
  public void clear() throws CacheException {
    redisTemplate.delete(this.keys());
  }

  @Override
  public int size() {
    return this.keys().size();
  }

  @Override
  public Set<String> keys() {
    return redisTemplate.keys(prefix + "*");
  }

  @Override
  public Collection<ValidatingSession> values() {
    Set<String> keys = keys();
    List<ValidatingSession> values = new ArrayList<>(keys.size());
    for (String k : keys) {
      values.add((ValidatingSession)redisTemplate.opsForValue().get(k));
    }
    return values;
  }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM