知識庫 / Spring / Spring Security RSS 訂閱

Spring Security 註冊 – 密碼編碼

Spring Security
HongKong
5
03:01 PM · Dec 06 ,2025
該文章是系列的一部分
• Spring Security 註冊系列
• 使用 Spring Security 的註冊過程
• 通過電子郵件激活新賬户
• Spring Security 註冊 – 發送驗證郵件
• 使用 Spring Security 註冊 – 密碼編碼 (當前文章)
• 註冊 API 變為 RESTful
• Spring Security – 重置密碼
• 註冊 – 密碼強度和規則
• 更新您的密碼
• 通知用户從新設備或位置登錄

1. 概述

本教程將討論註冊過程中的一個關鍵部分——密碼編碼,其本質是避免在純文本中存儲密碼。

Spring Security 支持幾種編碼機制,對於本教程,我們將使用 BCrypt,因為它通常是最佳解決方案。

其他機制,如 MD5PasswordEncoderShaPasswordEncoder,使用較弱的算法並且已被棄用。

2. 定義密碼編碼器

我們將首先定義簡單的BCryptPasswordEncoder作為配置中的一個Bean:

@Bean
public PasswordEncoder encoder() {
    return new BCryptPasswordEncoder();
}

較早的實現,例如 SHAPasswordEncoder,需要客户端在編碼密碼時傳遞鹽值。

然而,BCrypt 會 內部生成一個隨機鹽 替代。 這很重要,因為它意味着每次調用都會產生不同的結果,因此我們只需要編碼密碼一次。

為了使這種隨機鹽值生成工作,BCrypt 會將鹽值存儲在哈希值本身中。 例如,以下哈希值:

$2a$10$ZLhnHxdpHETcxmtEStgpI./Ri1mksgJ9iDP36FmfMdYyVg9g0b2dq

通過 $ 分隔三個字段:

  1. “2a” 表示 BCrypt 算法版本
  2. “10” 表示算法強度
  3. “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 註冊 – 發送驗證郵件
user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.