我在使用Spring Security时遇到了一个奇怪的情况。使用过:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> </parent>
通过以下简单的安全配置:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { UserDetails user = User.builder().username("1").password("1").roles("USER").build(); auth.inMemoryAuthentication().withUser(user).passwordEncoder(new BCryptPasswordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable().authorizeRequests().antMatchers("/inquiry").authenticated().anyRequest().permitAll().and() .httpBasic(); } }
我不断得到401Http状态代码。但是我更深入地研究了代码,并且我意识到在Spring安全核心中存在一个小问题。该类DaoAuthenticationProvider尝试使用BCrypt手边的密码编码器(在我的情况下)检查提供的密码是否与实际凭证匹配。所以
401
DaoAuthenticationProvider
BCrypt
if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword()))
但是在编码器中,的方法签名matches是:
matches
public boolean matches(CharSequence rawPassword, String encodedPassword)
因此,身份验证失败。
在安全配置中对BCrypt使用内存中身份验证时,需要首先对密码字符串进行加密。
所以你可以尝试
@Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // First encrypt the password string String encodedPassword = passwordEncoder().encode("1"); // Set the password UserDetails user = User.builder() .username("1") .password(encodedPassword) .roles("USER") .build(); // Use in-memory authentication with BCryptEncoder auth.inMemoryAuthentication() .withUser(user) .passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }