Java 按键的部分使Guava缓存无效

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 当外部存储中用户名的密码更改时,我需要删除用户名的缓存记录,但问题是密码仅存储为散列,而不是原始值,因此我不能仅构造新

我使用Guava LoadingCache缓存外部存储的身份验证请求。关键是对象身份验证:

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