首页 > 解决方案 > BCryptPasswordEncoder 会自动编码 Spring Security 创建的默认密码吗?

问题描述

我正在学习 Spring Security,并创建了一个简单的 RestController,它具有从数据库中检索数据的方法。

之后,我在 pom.xml 中添加了 Spring Security 依赖项。Spring 为我创建了用户名和密码。现在如果我想从数据库中检索数据,我需要使用这个用户名和密码。

之后,我想添加 BCryptPasswordEncoder,我只需在 SpringBootApplication 主类中添加以下代码:

@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
    return new BCryptPasswordEncoder();
}

现在,如果我尝试使用 Spring 创建的用户名和密码登录,它将无法正常工作。我想知道仅添加此代码是否会对 Spring 在幕后创建的默认密码进行编码?为什么当我尝试使用此密码登录时,Spring 不再对我的密码进行编码?登录时我应该添加什么代码来对密码进行编码?谢谢!

标签: spring-bootspring-securitybcryptrestful-authentication

解决方案


在不知道您使用的是什么版本的 Spring Security 的情况下,我将回答您将在 Spring Security 5 中执行的操作

@Bean
public PasswordEncoder passwordEncoder() {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

@Bean
public UserDetailsService userDetailsService() {
    return new InMemoryUserDetailsManager(
        User.builder()
            .passwordEncoder(input -> passwordEncoder().encode(input))
            .username("user")
            .password("{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG")
            .roles("USER")
            .build()
    );
}

委托密码编码器支持许多不同的密码格式,并会根据{bcrypt}前缀自动检测。

集成测试看起来像这样

@SpyBean
public UserDetailsService userDetailsService;

private User.UserBuilder user = User.withDefaultPasswordEncoder()
    .username("user")
    .password("password")
    .roles("USER");

@Test
@DisplayName("form login works")
void happyPath() throws Exception {
    doReturn(user.build())
        .when(userDetailsService).loadUserByUsername(any(String.class));
    mvc.perform(
        MockMvcRequestBuilders.post("/login")
            .param("username", "user")
            .param("password", "password")
    )
        .andExpect(status().is3xxRedirection())
        .andExpect(redirectedUrl("/"))
        .andExpect(authenticated())
    ;
}

如您所见,服务器以 bcrypt 格式存储密码。客户端以明文形式发送 ( .param("password", "password"))

我使用了一个 spybean,以便我可以修改 UserDetailsS​​ervice 返回的内容。因为它有缓存东西的习惯。

示例项目可在线获取


推荐阅读