該文章是系列的一部分
• Spring Security 註冊系列
• 使用 Spring Security 的註冊過程
• 通過電子郵件激活新賬户
• Spring Security 註冊 – 發送驗證郵件
• Spring Security – 重置密碼
• 註冊 – 密碼強度和規則
• 更新您的密碼
• 通知用户從新設備或位置登錄
• 使用 Spring Security 的註冊過程
• 通過電子郵件激活新賬户
• Spring Security 註冊 – 發送驗證郵件
• 使用 Spring Security 註冊 – 密碼編碼 (當前文章)
• 註冊 API 變為 RESTful
• Spring Security – 重置密碼
• 註冊 – 密碼強度和規則
• 更新您的密碼
• 通知用户從新設備或位置登錄
1. 概述
本教程將討論註冊過程中的一個關鍵部分——密碼編碼,其本質是避免在純文本中存儲密碼。
Spring Security 支持幾種編碼機制,對於本教程,我們將使用 BCrypt,因為它通常是最佳解決方案。
其他機制,如 MD5PasswordEncoder 和 ShaPasswordEncoder,使用較弱的算法並且已被棄用。
2. 定義密碼編碼器
我們將首先定義簡單的BCryptPasswordEncoder作為配置中的一個Bean:
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}較早的實現,例如 SHAPasswordEncoder,需要客户端在編碼密碼時傳遞鹽值。
然而,BCrypt 會 內部生成一個隨機鹽 替代。 這很重要,因為它意味着每次調用都會產生不同的結果,因此我們只需要編碼密碼一次。
為了使這種隨機鹽值生成工作,BCrypt 會將鹽值存儲在哈希值本身中。 例如,以下哈希值:
$2a$10$ZLhnHxdpHETcxmtEStgpI./Ri1mksgJ9iDP36FmfMdYyVg9g0b2dq通過 $ 分隔三個字段:
- “2a” 表示 BCrypt 算法版本
- “10” 表示算法強度
- “ZLhnHxdpHETcxmtEStgpI.” 部分實際上是隨機生成的鹽。基本上,前 22 個字符是鹽。最後一個字段的其餘部分是明文的實際哈希版本。
請注意,BCrypt 算法會生成長度為 60 的字符串,因此我們需要確保密碼存儲在能夠容納它的列中。常見的錯誤是創建不同長度的列,然後在身份驗證時出現無效用户名或密碼錯誤。
3. 註冊時對密碼進行編碼
我們將使用 PasswordEncoder 在我們的 UserService 中,在用户註冊過程中對密碼進行哈希處理:
示例 3.1. UserService 對密碼進行哈希處理
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public User registerNewUserAccount(UserDto accountDto) throws EmailExistsException {
if (emailExist(accountDto.getEmail())) {
throw new EmailExistsException(
"There is an account with that email adress:" + accountDto.getEmail());
}
User user = new User();
user.setFirstName(accountDto.getFirstName());
user.setLastName(accountDto.getLastName());
user.setPassword(passwordEncoder.encode(accountDto.getPassword()));
user.setEmail(accountDto.getEmail());
user.setRole(new Role(Integer.valueOf(1), user));
return repository.save(user);
}4. 在身份驗證時對密碼進行編碼
現在我們將處理這個過程的另一半,並在用户身份驗證時對密碼進行編碼。
首先,我們需要將我們在前面定義的密碼編碼 Bean 注入到我們的身份驗證提供程序中:
@Autowired
private UserDetailsService userDetailsService;
@Bean
public DaoAuthenticationProvider authProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(encoder());
return authProvider;
}安全配置非常簡單:
- 我們注入我們的用户詳情服務實現
- 我們定義一個認證提供者,該提供者引用我們的詳情服務
- 我們還啓用密碼編碼器
最後,我們需要在我們的安全 XML 配置中引用該認證提供者:
<authentication-manager>
<authentication-provider ref="authProvider" />
</authentication-manager>或者,如果我們使用 Java 配置:
@Configuration
@ComponentScan(basePackages = { "com.baeldung.security" })
@EnableWebSecurity
public class SecSecurityConfig {
@Bean
public AuthenticationManager authManager(HttpSecurity http) throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class)
.authenticationProvider(authProvider())
.build();
}
...
}5. 結論
本文繼續介紹註冊系列,展示瞭如何通過利用強大的 BCrypt 實現,正確地將密碼存儲在數據庫中。
下一頁 »
註冊 API 變為 RESTful
« 上一頁
Spring Security 註冊 – 發送驗證郵件