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,功能十分完善,有需要请留言,当然也可在网上搜索。

猜你喜欢

转载自blog.csdn.net/quanaianzj/article/details/84024685