知識庫 / Spring / Spring Security RSS 訂閱

Spring Security 默認密碼編碼器

Spring Security
HongKong
10
01:43 PM · Dec 06 ,2025

1. 概述

在 Spring Security 4 中,可以使用內存身份驗證方式存儲密碼,即明文存儲密碼。

Spring Security 5 中的密碼管理流程進行了重大改進,引入了更安全的默認機制,用於編碼和解碼密碼。這意味着,如果您的 Spring 應用存儲密碼為明文,升級到 Spring Security 5 可能會導致問題。

在本簡短教程中,我們將描述這些潛在問題,並演示解決方案。

2. Spring Security 4

我們將首先展示一個標準的安全配置,它提供簡單的基於內存的身份驗證(適用於 Spring 4):

@Configuration
public class InMemoryAuthWebSecurityConfigurer 
  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) 
      throws Exception {
        auth.inMemoryAuthentication()
          .withUser("spring")
          .password("secret")
          .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          .antMatchers("/private/**")
          .authenticated()
          .antMatchers("/public/**")
          .permitAll()
          .and()
          .httpBasic();
    }
}

此配置定義了所有對 /private/ 映射方法以及 /public/ 下一切內容的身份驗證。

如果在 Spring Security 5 中使用相同的配置,將會出現以下錯誤:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

錯誤表明提供的密碼由於未配置內存身份驗證的密碼編碼器,因此無法解碼

3. Spring Security 5

我們可以通過定義一個 DelegatingPasswordEncoderPasswordEncoderFactories 類一起,來解決此問題。

我們使用此編碼器來配置我們的用户:

@Configuration
public class InMemoryAuthWebSecurityConfigurer {

    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        UserDetails user = User.withUsername("spring")
            .password(encoder.encode("secret"))
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}

現在,使用這種配置,我們使用BCrypt將密碼存儲在以下格式中:

{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS

雖然我們可以定義自己的密碼編碼器集,但建議使用 默認編碼器,這些編碼器位於 PasswordEncoderFactories 中。

自 Spring Security 5.7.0-M2 版本起,Spring 已棄用 WebSecurityConfigureAdapter 並建議在不使用它的情況下創建配置。 這篇文章 會更詳細地解釋這一點。

3.2. NoOpPasswordEncoder

如果出於某種原因,我們不想對配置的密碼進行編碼,我們可以利用 NoOpPasswordEncoder

要做到這一點,我們只需將提供的密碼短語前綴到 password() 方法,並使用 {noop} 標識符:

@Configuration
public class InMemoryNoOpAuthWebSecurityConfigurer {

    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user = User.withUsername("spring")
            .password("{noop}secret")
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}

這樣一來,Spring Security 將在比較用户提供的密碼與我們配置的密碼時,在底層使用 NoOpPasswordEncoder

不過,請注意 我們絕不應該在生產應用程序中使用這種方法!正如官方文檔所説,NoOpPasswordEncoder 已經被棄用,這表示它是一個遺留實現,使用它被認為是不安全的。

3.3. 現有密碼遷移

我們可以通過以下步驟將現有密碼更新為推薦的 Spring Security 5 標準:

  • 使用編碼方式更新存儲為純文本的密碼值。
String encoded = new BCryptPasswordEncoder().encode(plainTextPassword);
  • 使用已知編碼器標識符對哈希存儲的密碼進行前綴:
{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
<ul>
 <li>要求用户在不知道存儲密碼的編碼機制時更新密碼</li>
</li >

4. 結論

在本快速示例中,我們使用新的密碼存儲機制,將有效的 Spring 4 內嵌式身份驗證配置更新為 Spring 5。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.