以下配置基于spring boot版本1.4.2.RELEASE湃交,默認(rèn)引入的spring security版本為4.1.3.RELEASE,頁面模板采用thymeleaf。
在MyUserDetailsService實(shí)現(xiàn)了UserDetailsService接口以后,在重寫的loadUserByUsername方法里驗(yàn)證用戶名不存在時(shí),我們會(huì)拋出一個(gè)UsernameNotFoundException異常或衡,比如:
throw new UsernameNotFoundException("用戶名不存在");
但是返回頁面以后, 發(fā)現(xiàn)并不能捕獲這個(gè)異常信息,通過[[${session.SPRING_SECURITY_LAST_EXCEPTION.message}]]方式獲得的異常信息始終是“Bad credentials”封断。
通過程序調(diào)試發(fā)現(xiàn)斯辰,系統(tǒng)在執(zhí)行到throw new UsernameNotFoundException("用戶名不存在")的時(shí)候,會(huì)執(zhí)行DaoAuthenticationProvider類的retrieveUser方法:
protected final UserDetails retrieveUser(String username,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
.............................
catch (UsernameNotFoundException notFound) {
if (authentication.getCredentials() != null) {
String presentedPassword = authentication.getCredentials().toString();
passwordEncoder.isPasswordValid(userNotFoundEncodedPassword,
presentedPassword, null);
}
throw notFound;
}
..........................
}
在這個(gè)方法會(huì)捕獲UsernameNotFoundException異常坡疼,繼續(xù)往下調(diào)試椒涯,會(huì)執(zhí)行到父抽象類AbstractUserDetailsAuthenticationProvider的authenticate方法:
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
....................
catch (UsernameNotFoundException notFound) {
logger.debug("User '" + username + "' not found");
if (hideUserNotFoundExceptions) {
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
..................
}
在這里會(huì)繼續(xù)捕獲到UsernameNotFoundException異常。
由于hideUserNotFoundExceptions的值為true回梧,所以這里會(huì)new一個(gè)新的BadCredentialsException異常拋出來废岂,那么最后捕獲到并放入session中的就是這個(gè)BadCredentialsException異常。
所以我們在頁面始終無法捕獲我們自定義的異常信息狱意。
這里提供兩個(gè)解決方案湖苞,當(dāng)然可能不是最好的,希望各位同學(xué)能夠給出更好的解決方案详囤。
第一個(gè)方案:
1.既然系統(tǒng)是捕獲UsernameNotFoundException類型的異常后再拋出新的BadCredentialsException異常财骨,那么我們干脆就不拋出UsernameNotFoundException異常。
我們模仿UsernameNotFoundException藏姐,創(chuàng)建自己的MyUsernameNotFoundException異常類隆箩。
public class MyUsernameNotFoundException extends AuthenticationException {
private static final long serialVersionUID = 1L;
public MyUsernameNotFoundException(String msg) {
super(msg);
}
public MyUsernameNotFoundException(String msg, Throwable t) {
super(msg, t);
}
}
2.在MyUserDetailsService類的loadUserByUsername方法拋出我們自己定義的MyUsernameNotFoundException異常。
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
.....................................
if (sysUser == null) {
throw new MyUsernameNotFoundException("用戶名不存在");
}
....................................
}
第二個(gè)方案:
在MyUserDetailsService類的loadUserByUsername方法直接拋出BadCredentialsException異常羔杨,這樣就不需要?jiǎng)?chuàng)建自己的MyUsernameNotFoundException異常類捌臊。
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
.....................................
if (sysUser == null) {
throw new BadCredentialsException("用戶名不存在");
}
....................................
}
好了,這樣在頁面通過[[${session.SPRING_SECURITY_LAST_EXCEPTION.message}]]兜材,就能顯示我們自定義的異常信息了理澎。