2016-09-30 472 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,旨在減緩密碼破解。