Spring Security异常没有直接抛出的问题

Spring Security 异常没有抛出去的问题

记录一个使用Spring Security自定义异常时出现的问题。

UserDetailsService returned null, which is an interface contract violation
环境描述

定义了一个登录异常,继承security里的Authentication异常

import org.springframework.security.core.AuthenticationException;


public class LoginException extends AuthenticationException {

    public LoginException(String msg, Throwable t) {
        super(msg, t);
    }

    public LoginException(String msg) {
        super(msg);
    }
}

在AuthenticationProvider里校检,并抛出异常

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        H5AuthenticationToken token = (H5AuthenticationToken) authentication;

        String username = (String) token.getPrincipal();
        String password = (String) token.getCredentials();

        int type = token.getType() == null ? 0 : token.getType();
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            throw new LoginException(String.format("用户名或%s不能为空!", type == 0 ? "验证码" : "密码"));
        }
        
        //这里省略项目里的加载用户代码
       ...
	}

定义登录失败处理类

public class LoginAuthFailHandler extends AbstractResponseHandler implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
        response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        response.setContentType("application/json; charset=utf-8");
        if(exception instanceof AuthenticationServiceException){
            String message = exception.getMessage();
            response.getWriter().write(Result.fail(10001,message).toString());
        }
    }

}

用postman测试接口,故意不输入password,让if语句执行为true,抛出异常。结果并没有返回我自定义的错误信息,而是返回以下信息

{
    "code": 10001,
    "msg": "UserDetailsService returned null, which is an interface contract violation"
}

控制台报错

org.springframework.security.authentication.InternalAuthenticationServiceException: UserDetailsService returned null, which is an interface contract violation
	at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:110) ~[spring-security-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:144) ~[spring-security-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
//以下省略
...
Debug查找原因

经过一番排查,发现问题出现在security框架里的ProviderManager类里,捕捉自定义异常后没有直接抛出,而是保存了异常,然后因为出现了新的异常而将自定义的异常覆盖了
在这里插入图片描述
)]

解决方案

将LoginException类,从继承AuthenticationException更改为继承InternalAuthenticationServiceException

public class LoginException extends InternalAuthenticationServiceException {

    public LoginException(String msg, Throwable t) {
        super(msg, t);
    }

    public LoginException(String msg) {
        super(msg);
    }
}

使ProviderManager类里捕捉到自定义异常时直接抛出

在这里插入图片描述

结果

成功解决

在这里插入图片描述

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值