You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何移除Spring Security中已弃用的NoOpPasswordEncoder?

移除已弃用的NoOpPasswordEncoder,同时保持Spring Security功能正常

当然可以移除NoOpPasswordEncoder!它被弃用的核心原因是明文存储密码极度不安全,Spring Security早就推荐使用强哈希算法来处理密码存储。下面是具体的改造方案,一步一步来:

1. 替换为安全的密码编码器

我们用Spring Security官方推荐的BCryptPasswordEncoder,它基于BCrypt哈希算法,自带加盐机制,能有效抵御彩虹表攻击。

首先在配置类里定义一个PasswordEncoder的Bean,方便整个应用复用:

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

2. 修改内存认证配置

接下来调整configureGlobal方法,移除NoOpPasswordEncoder,改用我们定义的BCryptPasswordEncoder,同时要把明文密码换成加密后的哈希值(可以动态生成,也可以提前生成好)。

修改后的完整配置类:

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
                // 注意规则顺序:先放行不需要认证的路径,再设置全局认证要求
                .antMatchers("/").permitAll()
                .anyRequest().fullyAuthenticated()
            .and()
            .formLogin()
                .loginPage("/login").permitAll()
                .defaultSuccessUrl("/", true)
            .and()
            .logout().permitAll()
            .and()
            .httpBasic();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder authBuilder, PasswordEncoder passwordEncoder) throws Exception {
        authBuilder.inMemoryAuthentication()
                .passwordEncoder(passwordEncoder)
                // 动态加密明文密码
                .withUser("user")
                    .password(passwordEncoder.encode("user"))
                    .roles("USER")
                .and()
                .withUser("admin")
                    .password(passwordEncoder.encode("admin"))
                    .roles("USER", "ADMIN");
    }
}

小提示:调整规则顺序

注意我修改了authorizeRequests的顺序——Spring Security的规则是从上到下匹配,如果先写anyRequest().fullyAuthenticated(),再写antMatchers("/").permitAll(),那根路径/也会被要求认证,之前的代码顺序有逻辑问题,现在调整后才是正确的。

3. 测试代码无需修改

你的测试代码完全不用动:

@RunWith(SpringJUnit4ClassRunner.class)
@AutoConfigureMockMvc
@SpringBootTest
public class SpringSecurityConfigTest {
    @Autowired
    MockMvc mockMvc;

    @Test
    public void userIsAuthenticatedTest() throws Exception {
        mockMvc.perform(formLogin().user("admin").password("admin"))
                .andExpect(authenticated());
    }
}

formLogin会自动使用我们配置的PasswordEncoder对传入的明文密码进行加密,再和内存中存储的哈希值比对,测试依然能正常通过。

可选优化:提前生成哈希值

如果你不想每次启动应用都重新加密密码,可以提前生成BCrypt哈希值(比如写个小代码片段生成),然后直接把哈希值写在代码里,比如:

.withUser("user")
    .password("$2a$10$EblZqNptyYvcLm/VwDCVAuBjzZOI7khzdyGPBr08PpIi0na624b8.") // 对应明文"user"的BCrypt哈希
    .roles("USER")

这样改造后,你就彻底摆脱了已弃用的NoOpPasswordEncoder,同时功能完全正常,还大幅提升了密码存储的安全性!

内容的提问来源于stack exchange,提问作者Dmytro Manzhula

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:05:47