1. 程式人生 > >springboot1.5.3+shiro1.3.2+redis單節點及叢集整合

springboot1.5.3+shiro1.3.2+redis單節點及叢集整合

專案要求直接在配置檔案中可切換redis單節點和叢集模式,以前依賴shiro-redis開源專案,雖然可切換但有點麻煩,研究藉助spring-data-redis直接整合。

一、配置檔案

spring:
	redis:
	    database: 0
	    host: redis
	    password:
	    port: 6379
	    timeout: 60000
	    #cluster:
	      #nodes: 127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005
pool: max-active: 80 max-idle: 8 max-wait: -1 min-idle: 0

上面是單節點配置,叢集去掉註釋cluster,及nodes.如下:

spring:
	redis:
	    database: 0
	    # host: redis
	    password:
	    # port: 6379
	    timeout: 60000
	    cluster:
	      nodes: 127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,
127.0.0.1:7004,127.0.0.1:7005 pool: max-active: 80 max-idle: 8 max-wait: -1 min-idle: 0

上述host及port也可不註釋,優先使用叢集模式。

二、shiro配置

@Configuration
public class ShiroConfig {


	@Autowired
	private RedisTemplate redisTemplate;


	/**
	 *  自己實現
	 *  @title systemCredentilsMatch
	 *  @description 密碼驗證器
	 *	@param 
	 *  @return SimpleCredentialsMatcher 返回型別
	 *  @throws
	 */
@Bean public SimpleCredentialsMatcher systemCredentilsMatch(){ return new SystemCredentilsMatch(); } /** *  自己的realm * @title systemShiroRealms * @description 身份認證以及授權 * @param * @return SystemShiroRealms 返回型別 * @throws */ @Bean public SystemShiroRealms systemShiroRealms(){ SystemShiroRealms systemShiroRealms = new SystemShiroRealms(); systemShiroRealms.setCredentialsMatcher(systemCredentilsMatch()); return systemShiroRealms; } /** * * @title systemSessionManager * @description session管理器設定 * @param * @return SystemSessionManager 返回型別 * @throws */ @Bean public SystemSessionManager systemSessionManager(){ SystemSessionManager systemSessionManager = new SystemSessionManager(); systemSessionManager.setSessionDAO(new EnterpriseCacheSessionDAO()); return systemSessionManager; } /** * 實現shiroRedisCacheManager * @author tanaq * @date 18-11-12 下午4:45 * @param [template] * @throws * @return com.cusc.icall.config.ShiroRedisCacheManager * */ private ShiroRedisCacheManager cacheManager(){ return new ShiroRedisCacheManager(redisTemplate); } /** * * @title securityManager * @description shiro安全管理器配置 * @param * @return SecurityManager 返回型別 * @throws */ @Bean public SecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setCacheManager(cacheManager()); securityManager.setSessionManager(systemSessionManager()); securityManager.setRealm(systemShiroRealms()); return securityManager; } /** * * @title shiroFilterFactoryBean * @description Shiro核心過濾器配置 * @param * @return ShiroFilterFactoryBean 返回型別 * @throws */ @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager()); Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); filterChainDefinitionMap.put("/ai/**", "authc"); filterChainDefinitionMap.put("/ai/*", "authc"); filterChainDefinitionMap.put("/druid/**","anon"); filterChainDefinitionMap.put("/**", "anon"); //配置Shiro預設跳轉至登入地址時,將以json格式資料返回 shiroFilterFactoryBean.setLoginUrl("/unAuth"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } /** * * @title defaultAdvisorAutoProxyCreator * @description 開啟自動代理 * @param * @return DefaultAdvisorAutoProxyCreator 返回型別 * @throws */ @Bean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator(); proxyCreator.setProxyTargetClass(true); return proxyCreator; } /** * * @title authorizationAttributeSourceAdvisor * @description 開啟許可權認證 * @param * @return AuthorizationAttributeSourceAdvisor 返回型別 * @throws */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; } }

三、ShiroRedisCacheManager 類實現shiro操作redis

本類已在上面的shiro配置中。給出實現:

public class ShiroRedisCacheManager extends AbstractCacheManager {

    private RedisTemplate<byte[],byte[]> redisTemplate;

    public ShiroRedisCacheManager(RedisTemplate redisTemplate){
        this.redisTemplate = redisTemplate;
    }

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

class ShiroRedisCache<K,V> implements Cache<K,V> {
    private RedisTemplate redisTemplate;
    private String prefix = "ntspcc_shiro_redis";

    public String getPrefix() {
        return prefix+":";
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public ShiroRedisCache(RedisTemplate redisTemplate){
        this.redisTemplate = redisTemplate;
    }

    public ShiroRedisCache(RedisTemplate redisTemplate,String prefix){
        this(redisTemplate);
        this.prefix = prefix;
    }

    @Override
    public V get(K k) throws CacheException {
        if (k == null) {
            return null;
        }
        byte[] bytes = getBytesKey(k);
        return (V)redisTemplate.opsForValue().get(bytes);

    }

    @Override
    public V put(K k, V v) throws CacheException {
        if (k== null || v == null) {
            return null;
        }

        byte[] bytes = getBytesKey(k);
        redisTemplate.opsForValue().set(bytes, v);
        return v;
    }

    @Override
    public V remove(K k) throws CacheException {
        if(k==null){
            return null;
        }
        byte[] bytes =getBytesKey(k);
        V v = (V)redisTemplate.opsForValue().get(bytes);
        redisTemplate.delete(bytes);
        return v;
    }

    @Override
    public void clear() throws CacheException {
        redisTemplate.getConnectionFactory().getConnection().flushDb();

    }

    @Override
    public int size() {
        return redisTemplate.getConnectionFactory().getConnection().dbSize().intValue();
    }

    @Override
    public Set<K> keys() {
        byte[] bytes = (getPrefix()+"*").getBytes();
        Set<byte[]> keys = redisTemplate.keys(bytes);
        Set<K> sets = new HashSet<>();
        for (byte[] key:keys) {
            sets.add((K)key);
        }
        return sets;
    }

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

    private byte[] getBytesKey(K key){
        if(key instanceof String){
            String prekey = this.getPrefix() + key;
            return prekey.getBytes();
        }else {
            return SerializeUtil.serialize(key);
        }
    }

}


四、總結

上述整合完畢,操作redis可使用,可使用RedisTemplate.這裡已準備好了包裝類RedisTemplateUtils,功能十分完善,有需要請留言,當然也可在網上搜索。