灼眼de涙 2016-11-28 02:10 采纳率: 100%
浏览 7938
已采纳

shiro-redis集成时,权限的缓存清空存在一个bug

用的这个jar包: org.crazycake.shiro

@Override
public void clearAllCachedAuthorizationInfo() {
Cache cache = getAuthorizationCache();
if (cache != null) {
for (Object key : cache.keys()) {
cache.remove(key);
}
}
}
清空所有的权限缓存时 调用这个方法的时候,会调用 redis的 keys的方法 如下
public Set keys() {
try {
Set keys = cache.keys(this.keyPrefix + "*");
if (CollectionUtils.isEmpty(keys)) {
return Collections.emptySet();
}else{
Set newKeys = new HashSet();
for(byte[] key:keys){
newKeys.add((K)key);
}
return newKeys;
}
} catch (Throwable t) {
throw new CacheException(t);
}
}

    private byte[] getByteKey(K key){
    if(key instanceof String){
        String preKey = this.keyPrefix + key;
        return preKey.getBytes();
    }else{
        return SerializeUtils.serialize(key);
    }
}

@Override
public V get(K key) throws CacheException {
    logger.debug("根据key从Redis中获取对象 key [" + key + "]");
    try {
        if (key == null) {
            return null;
        }else{
            byte[] rawValue = cache.get(getByteKey(key));
            @SuppressWarnings("unchecked")
            V value = (V)SerializeUtils.deserialize(rawValue);
            return value;
        }
    } catch (Throwable t) {
        throw new CacheException(t);
    }

}
因   权限缓存时 用的是 PrincipalCollection 这个对象当作的key
所以会调用 SerializeUtils.serialize(key); 这个方法  如下:
public static byte[] serialize(Object object) {

    byte[] result = null;

    if (object == null) {
        return new byte[0];
    }
    try {
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream(128);
        try  {
            if (!(object instanceof Serializable)) {
                throw new IllegalArgumentException(SerializeUtils.class.getSimpleName() + " requires a Serializable payload " +
                        "but received an object of type [" + object.getClass().getName() + "]");
            }
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteStream);
            objectOutputStream.writeObject(object);
            objectOutputStream.flush();
            result =  byteStream.toByteArray();
        }
        catch (Throwable ex) {
            throw new Exception("Failed to serialize", ex);
        }
    } catch (Exception ex) {
        logger.error("Failed to serialize",ex);
    }
    return result;
}

这样是把 权限缓存到redis之中了,但是取的时候确是有问题的
最开始说的keys 方法之中 
cache.keys(this.keyPrefix + "*");
取时 用了 this.keyPrefix+“*” 来取  而这个前缀 在存的时候根本没有当作key的前缀,所以根本取不出来

有没有大神 指点一波 
难道只有改源码了么?
  • 写回答

2条回答 默认 最新

  • 灼眼de涙 2016-11-28 09:55
    关注
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 求.net core 几款免费的pdf编辑器
  • ¥20 SQL server表计算问题
  • ¥15 C# P/Invoke的效率问题
  • ¥20 thinkphp适配人大金仓问题
  • ¥20 Oracle替换.dbf文件后无法连接,如何解决?(相关搜索:数据库|死循环)
  • ¥15 数据库数据成问号了,前台查询正常,数据库查询是?号
  • ¥15 算法使用了tf-idf,用手肘图确定k值确定不了,第四轮廓系数又太小才有0.006088746097507285,如何解决?(相关搜索:数据处理)
  • ¥15 彩灯控制电路,会的加我QQ1482956179
  • ¥200 相机拍直接转存到电脑上 立拍立穿无线局域网传
  • ¥15 (关键词-电路设计)