2013-06-21 26 views
13

今天我將我正在使用的應用程序的spring安全版本從3.1.3升級到3.1.4,並且我注意到org.springframework.security.authentication.encoding.ShaPasswordEncoder類中的棄用警告。Spring安全3.1.4和ShaPasswordEncoder棄用

所以我切換到新的org.springframework.security.crypto.password.StandardPasswordEncoder實施。

我讓它工作,我可以在我的應用程序中註冊一個新用戶並登錄,但正如我擔心的那樣,我無法使用以前的ShaPasswordEncoder和我的自定義鹽生成的密碼登錄。

由於我有一個數據庫,許多用戶已經註冊,我應該怎麼做切換實現而不使舊的編碼密碼失效? 它甚至有可能嗎?

參見:How to use new PasswordEncoder from Spring Security

回答

17

如果你想切換到更安全的密碼編碼機制,那麼我會建議你使用BCrypt。我會用這樣的遷移用戶:

// Implement the old PasswordEncoder interface 
public class MigrateUsersPasswordEncoder implements PasswordEncoder { 
    @Autowired 
    ShaPasswordEncoder legacyEncoder; 
    @Autowired 
    JdbcTemplate template; 

    BCryptPasswordEncoder bcryptEncoder = new BCryptPasswordEncoder(); 

    @Override 
    public String encodePassword(String rawPass, Object salt) { 
     return bcryptEncoder.encode(rawPass); 
    } 

    @Override 
    public boolean isPasswordValid(String encPass, String rawPass, Object salt) { 
     if (legacyEncoder.isPasswordValid(encPass, rawPass, salt)) { 
      template.update("update users set password = ? where password = ?", bcryptEncoder.encode(rawPass), encPass); 
      return true; 
     } 
     return bcryptEncoder.matches(rawPass, encPass); 
    } 
} 

您可以查看哪些用戶的比例已經由密碼字段的格式遷移。 BCrypt字符串有一個以$符號開頭的獨特語法。

其他答案之一指出,此代碼可能會意外更新多個密碼在同一時間。這個問題表明,正在使用一種定製鹽,所以如果隨機選擇鹽,碰撞機率可以忽略不計,但情況並非總是如此。如果更新了兩個密碼,問題會是什麼?然後就可以檢測到帳號與bcrypt哈希具有相同的密碼。無論如何,情況就是這樣,因爲它要求SHA哈希值與更新發生時相同。如果您認爲這可能是一個問題(例如,因爲選擇不好的鹽或者使用無鹽散列),修改SQL以檢測此問題並使用單獨的BCrypt散列值執行多個更新將很微不足道。

+0

感謝您的代碼。這或多或少是Spiff建議的。我的目標是能夠升級到未來版本的Spring Security,而不需要同時實現兩個實現,此解決方案僅在每個用戶都登錄時纔有效。我希望它會引入一個與舊版兼容的實現ShaPasswordEncoder。 –

+0

如果用戶從未登錄過,那麼可能需要決定帳戶是否值得維護(經過適當的審閱期後)。如果它們不活動,您可以暫時禁用它們並向用戶發送郵件,要求他們重置密碼。不鼓勵使用舊的密碼編碼器,因爲它們相對不安全,容易出錯並且與其他系統不兼容。這些類已棄用,以阻止它們在新應用程序中的使用,但如果您不想使用更安全的選項,則無法阻止您使用它們。 –

1

這是一個很好的問題,我期待着閱讀一些答案。我們不可能在一次大規模更新中做到這一點:您無法從哈希中檢索原始字符串。如果提交的密碼與任一策略匹配並在必要時將其轉換爲新策略,則必須在登錄嘗試期間進行檢查,但這意味着您必須同時使用兩種編碼策略,直到所有用戶都已登錄,因此所有密碼都已轉換。對於新開發人員來說,這不是非常方便,也不一定直觀。

2

我試圖給接受的答案添加評論,但唉,我還沒有足夠的信譽。 :(

我認爲接受答案的代碼片段在更新數據庫中的密碼的地方是潛在的危險如果ShaPasswordEncoder在加密時產生相同的結果(這就是爲什麼假定可以找到舊密碼,並且我證實這至少在ShaPasswordEncoder中是無效的),但您仍然無法保證密碼在所有用戶中都是唯一的。您可以偶然與系統上的其他用戶共享相同的密碼,並且SQL代碼最終會改變所有碰巧擁有密碼的用戶

我認爲最安全的策略是不更新用戶的密碼,而是提供一個遷移策略,計劃最終刪除ShaPasswor dEncoder。

  • 使用提供的示例代碼。
  • 刪除更新數據庫的代碼。
  • 添加「忘記密碼」或「生成新密碼」等功能,以處理用戶在刪除ShaPasswordEncoder時未創建新密碼的最終情況。就像你升級到Spring Security時刪除它,或者選擇自己刪除它一樣。
  • 更新您的文檔或明確指出,在下一個主要發行版本的軟件中,用戶將不得不重新保存他們的密碼或將不得不使用前面提到的密碼重置功能。
  • 給用戶一個主要版本發佈週期的寬限期過渡(他們可能不會這樣做,只是被重置密碼所困住)。
+0

這是一個很好的觀點。但是,我認爲與現有情況相比,這並不是很危險,或者推遲更新。解決方法也很簡單。我更新了我的答案,增加了一些額外的想法。 –