转载 

Spring Boot + Spring Security解决UsernameNotFoundException无法被捕获的问题

分类:    508人阅读    IT小君  2018-02-22 21:47

以下配置基于spring boot版本1.4.2.RELEASE,默认引入的spring security版本为4.1.3.RELEASE,页面模板采用thymeleaf。

在MyUserDetailsService实现了UserDetailsService接口以后,在重写的loadUserByUsername方法里验证用户名不存在时,我们会抛出一个UsernameNotFoundException异常,比如:


throw new UsernameNotFoundException("用户名不存在");


但是返回页面以后, 发现并不能捕获这个异常信息,通过[[${session.SPRING_SECURITY_LAST_EXCEPTION.message}]]方式获得的异常信息始终是“Bad credentials”。

通过程序调试发现,系统在执行到throw new UsernameNotFoundException("用户名不存在")的时候,会执行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;
        }
        ..........................

    }

在这个方法会捕获UsernameNotFoundException异常,继续往下调试,会执行到父抽象类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"));
                }
        ..................

    }

在这里会继续捕获到UsernameNotFoundException异常。
由于hideUserNotFoundExceptions的值为true,所以这里会new一个新的BadCredentialsException异常抛出来,那么最后捕获到并放入session中的就是这个BadCredentialsException异常。
所以我们在页面始终无法捕获我们自定义的异常信息。

这里提供两个解决方案,当然可能不是最好的,希望各位同学能够给出更好的解决方案。

第一个方案:
1.既然系统是捕获UsernameNotFoundException类型的异常后再抛出新的BadCredentialsException异常,那么我们干脆就不抛出UsernameNotFoundException异常。
我们模仿UsernameNotFoundException,创建自己的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("用户名不存在");
        }  
        ....................................
    }
第二个方案:
在MyUserDetailsService类的loadUserByUsername方法直接抛出BadCredentialsException异常,这样就不需要创建自己的MyUsernameNotFoundException异常类。


public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {  
        
        .....................................
        if (sysUser == null) {  
            throw new BadCredentialsException("用户名不存在");
        }  
        ....................................
    }
好了,这样在页面通过[[${session.SPRING_SECURITY_LAST_EXCEPTION.message}]],就能显示我们自定义的异常信息了。




点击广告,支持我们为你提供更好的服务

网页设计开发公司网站模板

html5 svg夜空中星星流星动画场景特效

HTML5现代家居装潢公司网站模板

html5图标下拉搜索框自动匹配代码

响应式太阳能能源公司网站模板

jQuery右端悬浮带返回顶部特效

HTML5 Canvas竖直流动线条背景动画特效

有机水果蔬菜HTML5网站模板

html5 canvas进度条圆环图表统计动画特效

html5 canvas彩色碎片组合球形旋转动画特效

小众时尚单品在线电子商务网站模板

中小型创意设计服务公司网站模板

现代时尚家具公司网站模板

canvas炫酷鼠标移动文字粒子特效

响应式时尚单品在线商城网站模板

响应式咖啡饮品宣传网站模板

css+js实现的颜色渐变数字时钟动画特效

css鼠标跟随文字模糊特效

HTML5数字产品服务公司网站模板

js+css3抽奖转盘旋转点餐代码

点击广告,支持我们为你提供更好的服务
 工具推荐 更多»
点击广告,支持我们为你提供更好的服务