我正在使用Guava LoadingCache来缓存外部存储的身份验证请求。关键是对象Auth:
cap.set
,响应是HttpStatus,OK或FORBIDDEN。
当更改外部存储中public class Auth {
private String username;
private String password;
public boolean equals(Object o);
}
的密码时,我需要删除username
的缓存记录,但问题是密码只存储为哈希,而不是原始值,所以我无法构建新的Auth对象以进行失效,例如:
username
如何仅使用cache.invalidate(new Auth(<username>, <password>));
值来使缓存记录无效?
答案 0 :(得分:4)
例如,我在缓存中有两条记录:Auth(user1,password1)= OK和Auth(user1,password2)= FORBIDDEN。所以password1是正确的,而password2是不正确的。如果我通过Auth(user1,password2)收到更多的请求,我只返回FORBIDDEN而不查询外部存储。
这个问题是你几乎再也看不到Auth(user1, password2)
(即无效的一对)。合法用户可能会犯错,他们可能会重复完全相同的错误,但这种情况很少见。攻击者在重复失败的组合时不会浪费时间。所以这样的条目只是浪费了记忆。
将user
作为密钥存储,password
或hashedPassword
作为值应该可以正常工作,如果点击,它将为您节省外部存储访问权限:您只需要一个比较和散列。
虽然我不认为您的问题有意义,但我尝试提出一个解决方案:通过一部分密钥无效,但您可以保留一组所有用户最近更改了密码(例如,在过去24小时内)。如果您将expireAfterWrite
设置为较小的值,则可以通过查看该集来确定可以检测到无效的Auth
。
请注意,MD5保护密码的时间非常短。有更好的算法,如bcrypt
或bcrypt
,旨在减缓密码破解。
答案 1 :(得分:1)
如何实现在驱逐时执行的RemovalListener并删除密钥,例如来自基于键值对的单独数据结构的用户名。
答案 2 :(得分:1)
怎么样?
第二个选项是使用user
作为缓存键,使用the password hash
作为值而不是服务响应的缓存
答案 3 :(得分:0)
在我看来缓存密码而不是哈希是不好的做法。 密钥可以只是用户名或用户名和哈希。