一、故障现象
1.代码:
Reference:
org.springframework.security.core.userdetails.UserDetailsService;
//代码片段:
@Service
public class UserRepositoryUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
public UserRepositoryUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user != null) {
return user;
}
//throw new BadCredentialsException("帐号不存在,请重新输入");
throw new UsernameNotFoundException("User '" + username + "' not found!");
}
}
2.现象:
当登录用户不存在时,应当回显 "User 'username' not found! ",但实际显示为 Bad credentials 。
二、原因
1.源码:
Reference:
org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider#authenticate;
//代码片段:
catch (UsernameNotFoundException ex) {
this.logger.debug("Failed to find user '" + username + "'");
if (!this.hideUserNotFoundExceptions) {
throw ex;
}
throw new BadCredentialsException(this.messages
.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
2.释义:
在 AbstractUserDetailsAuthenticationProvider 中,hideUserNotFoundExceptions 默认为 true,所以没有抛出 UsernameNotFoundException 这个异常,而是将其转换为 BadCredentialsException
三、解决方案
1.修正:
Reference:
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
org.springframework.security.core.userdetails.UserDetailsService;
org.springframework.security.crypto.password.PasswordEncoder;
org.springframework.security.authentication.dao.DaoAuthenticationProvider;
//代码片段:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("userRepositoryUserDetailsService")
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setHideUserNotFoundExceptions(false);
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(this.passwordEncoder());
return provider;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(daoAuthenticationProvider());
}
}
2.释义:
将hideUserNotFoundExceptions 设置为 false;并于 Spring Security 的 WebSecurityConfigurer 中进行配置