在项目中用到了Spring Security 进行登录校验,我们实现了其UserDetailsService接口的loadUserByUsername()方法,并在其中定义了异常信息,通过UsernameNotFoundException异常类抛出,但是在结果中并未获取到我们自定义的异常msg,而是获取的"用户名或密码错误"(Spring Security自带的)。这让我百思不得其解。
于是自己进行debug追踪代码。在AbstractUserDetailsAuthenticationProvider类中的retrieveUser()方法我们找到了答案,这里面先是调用了我们实现的loadUserByUsername()方法,然后抛出了UsernameNotFoundException异常,接着异常在AbstractUserDetailsAuthenticationProvider类中的authenticate()方法被捕捉。这里有一个很关键的判断:如果hideUserNotFoundExceptions为true,就抛出BadCredentialsException异常,而且异常的msg是从Spring Security框架自带的国际化配置文件中读取的,因此不会抛出我们自定义的异常,而是一直抛出“用户名或密码错误”。
retrieveUser()方法:
authenticate()方法:
解决方法
1.自己配置AuthenticationProvider Bean,并设置hideUserNotFoundExceptions=false.
@Bean
public DaoAuthenticationProvider authenticationProvider(){
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setPasswordEncoder(passwordEncoder());
provider.setUserDetailsService(userDetailsService);
provider.setHideUserNotFoundExceptions(false);
return provider;
}
2.自定义异常类,并在loadUserByUsername()方法中抛出。
3.在loadUserByUsername()方法中抛出BadCredentialsException异常,不要抛出UsernameNotFoundException异常。