2016-09-30 249 views
0

我正在使用Guava LoadingCache来缓存对外部存储的auth请求。关键是对象身份验证:通过部分密钥使Guava缓存失效

public class Auth { 
    private String username; 
    private String password; 
    public boolean equals(Object o); 
} 

并且响应是HttpStatus,OK或FORBIDDEN。

当外部存储中的username的密码发生变化时,我需要删除缓存记录username,但问题是密码只存储为散列值,而不是原始值,所以我不能仅仅构造新的验证对象为无效,如:

cache.invalidate(new Auth(<username>, <password>)); 

我怎么能无效缓存记录,只用username价值?

+0

为什么不使用'Auth'作为密钥? – mfulton26

+0

原因我不知道原始密码,只有存储的MD5哈希值。并且在缓存中我使用原始密码进行验证,因此它们不相等。 – mv200580

+0

我觉得很愚蠢,我的意思是,“为什么不使用'用户名'作为关键”? – mfulton26

回答

0

在我看来缓存密码,而不是散列是不好的做法。 关键可能只有用户名或用户名和散列。

1

如何实现在驱逐上执行的RemovalListener并删除密钥例如用户名来自基于键值对的单独数据结构。

1

什么

  • 穿行缓存键
  • 找改变用户
  • 无效的关键

第二个选项是使用user作为缓存键和the password hash作为值而不是缓存的服务响应

4

例如,我在缓存中有两条记录:Auth(user1,password1)= OK和Auth(user1,password2)= FORBIDDEN。所以password1是正确的,并且password2是不正确的。如果我通过Auth(user1,password2)收到更多的请求,我只是返回FORBIDDEN而不询问外部存储。

这样做的问题是您几乎再也看不到Auth(user1, password2)(即无效对)。合法用户可能犯了一个错误,他们可能会重复同样的错误,但这很少见。攻击者不会浪费时间重复失败的组合。所以这样的入口只是浪费了内存。

存储user为重点和passwordhashedPassword的值应该很好地工作,并在打它会为你节省外部存储访问的情况:你需要的是一个比较和散列。

虽然我不认为你的问题是有道理的,我试图提出一个解决方案:通过钥匙的一部分无效是不可能的,但你可以保留,而不是一组所有用户具有最近改变了他们的密码(例如,在过去的24小时内)。如果您将expireAfterWrite设置为较小的值,则可以确定通过查阅该集合可以检测到无效的Auth

请注意,仅通过MD5保护密码非常周。有很多更好的算法,如bcryptbcrypt,旨在减缓密码破解。