Java 按键的部分使Guava缓存无效
我使用Guava LoadingCache缓存外部存储的身份验证请求。关键是对象身份验证:Java 按键的部分使Guava缓存无效,java,caching,guava,Java,Caching,Guava,我使用Guava LoadingCache缓存外部存储的身份验证请求。关键是对象身份验证: public class Auth { private String username; private String password; public boolean equals(Object o); } 响应为HttpStatus、OK或FORBIDDEN 当外部存储中用户名的密码更改时,我需要删除用户名的缓存记录,但问题是密码仅存储为散列,而不是原始值,因此我不能仅构造新
public class Auth {
private String username;
private String password;
public boolean equals(Object o);
}
响应为HttpStatus、OK或FORBIDDEN
当外部存储中用户名
的密码更改时,我需要删除用户名
的缓存记录,但问题是密码仅存储为散列,而不是原始值,因此我不能仅构造新的Auth对象以使其失效,如:
cache.invalidate(new Auth(<username>, <password>));
cache.invalidate(新身份验证(,);
我怎样才能使缓存记录无效,只使用
用户名
值?在我看来,缓存密码而不是散列不是好的做法。
密钥只能是用户名或用户名和哈希。在我看来,缓存密码而不是哈希是不好的做法。
密钥只能是用户名或用户名和哈希。如何实现一个RemovalListener,它在逐出时执行,并从基于键值对的单独数据结构中删除密钥(例如用户名)。如何实现一个RemovalListener,它在逐出时执行,并将密钥(例如用户名)从数据结构中删除基于键值对的独立数据结构。如何
- 浏览缓存密钥
- 查找已更改的用户
- 使钥匙失效
user
作为缓存键,使用密码散列
作为值,而不是缓存服务响应怎么样
- 浏览缓存密钥
- 查找已更改的用户
- 使钥匙失效
user
作为缓存键,使用密码散列
作为值,而不是缓存服务响应
例如,我在缓存中得到了两条记录:Auth(user1,password1)=OK和Auth(user1,password2)=禁止。所以password1是正确的,password2是不正确的。如果我将通过Auth(user1,password2)收到多个请求,我只返回禁止,而不查询外部存储
问题是,您几乎再也看不到Auth(user1,password2)
(即无效对)。合法用户可能会犯错误,他们可能会重复完全相同的错误,但这种情况很少见。攻击者不会浪费时间重复失败的组合。所以这样的条目只是浪费了内存
将user
存储为键,将password
或hashedPassword
存储为值应该可以很好地工作,如果命中,它将为您节省外部存储访问:您所需要的只是比较和散列
虽然我认为您的问题没有意义,但我尝试提出一个解决方案:不可能通过密钥的一部分使其无效,但您可以保留一组最近(例如,在过去24小时内)更改了密码的所有用户。如果将expireAfterWrite
设置为较小的值,则可以通过查看该设置来确保检测到无效的Auth
请注意,仅使用MD5保护密码是非常困难的。有许多更好的算法,如bcrypt
或bcrypt
,旨在减缓密码破解
例如,我在缓存中得到了两条记录:Auth(user1,password1)=OK和Auth(user1,password2)=禁止。所以password1是正确的,password2是不正确的。如果我将通过Auth(user1,password2)收到多个请求,我只返回禁止,而不查询外部存储
问题是,您几乎再也看不到Auth(user1,password2)
(即无效对)。合法用户可能会犯错误,他们可能会重复完全相同的错误,但这种情况很少见。攻击者不会浪费时间重复失败的组合。所以这样的条目只是浪费了内存
将user
存储为键,将password
或hashedPassword
存储为值应该可以很好地工作,如果命中,它将为您节省外部存储访问:您所需要的只是比较和散列
虽然我认为您的问题没有意义,但我尝试提出一个解决方案:不可能通过密钥的一部分使其无效,但您可以保留一组最近(例如,在过去24小时内)更改了密码的所有用户。如果将expireAfterWrite
设置为较小的值,则可以通过查看该设置来确保检测到无效的Auth
请注意,仅使用MD5保护密码是非常困难的。有许多更好的算法,如
bcrypt
或bcrypt
,旨在减缓密码破解。为什么不使用Auth
作为密钥?因为我不知道原始密码,只知道存储的MD5哈希。我觉得很傻,我想问的是,“为什么不使用username
作为密钥?”以及它必须如何工作?例如,我在缓存中得到了两条记录:Auth(user1,password1)=OK和Auth(user1,password2)=禁止。所以password1是正确的,password2是不正确的。如果我将收到多个带有Auth(user1,password2)的请求,我只返回禁止,而不查询外部存储。如果我只使用用户名作为密钥,每次收到请求时我都需要查询存储。为什么不使用Auth
作为密钥?因为我不知道原始密码,只知道存储的MD5哈希。我觉得很傻,我想问的是,“为什么不使用username
作为密钥?”以及它必须如何工作?例如,我在缓存中得到了两条记录:Auth(user1,password1)=OK和Auth(user1,password2)=禁止。所以password1是正确的,password2是不正确的。如果我将通过Auth(user1,password2)收到多个请求,我只返回FORB