Spring boot 如果身份验证/授权失败,如何为Spring Security定制响应?

Spring boot 如果身份验证/授权失败,如何为Spring Security定制响应?,spring-boot,spring-security,Spring Boot,Spring Security,我正在开发一个SpringBoot应用程序,使用SpringSecurity检查用户登录成功或用户被授权访问其中的资源 现在,无论我输入了错误的用户名/密码还是用户被锁定,都会返回401 Unauthorized。我想自定义它,比如说,如果错误的凭据,它将返回400,如果用户被锁定,它将返回401 我已经为应用程序定义了自定义筛选器和身份验证入口点 public class JWTUsernameAndPasswordAuthenticationFilter extends UsernamePa

我正在开发一个SpringBoot应用程序,使用SpringSecurity检查用户登录成功或用户被授权访问其中的资源

现在,无论我输入了错误的用户名/密码还是用户被锁定,都会返回401 Unauthorized。我想自定义它,比如说,如果错误的凭据,它将返回400,如果用户被锁定,它将返回401

我已经为应用程序定义了自定义筛选器和身份验证入口点

public class JWTUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

   ....

   @Override
   public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
        throws AuthenticationException {
        Optional<UserEntity> userEntity = userService
            .findByUserId(request.getParameter("username"));
        if (userEntity.isPresent()) {
           if (userEntity.get().getStatus().equals("LOCKED")) {
              throw new BadCredentialsException("User is locked!"); //I want it to return status 403 here
           }
        }

        String privateKey = userService.findByUserId(request.getParameter("username")).get().getLoginKey();

        String username = request.getParameter("username");
        String password = CryptoUtil.decrypt(privateKey, request.getParameter("password"));

        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,
            password, Collections.emptyList());
        return authenticationManager.authenticate(authenticationToken);
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
        AuthenticationException failed) throws IOException, ServletException {
        String username = request.getParameter("username");
        try {
            // Do some process stuff....
        } catch (Exception ex) {
           log.error(ex);
        }
        super.unsuccessfulAuthentication(request, response, failed); // I want to return 400 here
    }
}


public class JwtAuthenticationExceptionEntryPoint implements AuthenticationEntryPoint {

    @Getter
    @Value("${application.version}")
    private String version;

    @Getter
    @Value("${application.name}")
    private String applicationName;

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
        AuthenticationException authException) throws IOException, ServletException {

         RESTFulStatus status = new RESTFulStatus(RESTFulStatus.STATUS_ERROR, HttpStatus.UNAUTHORIZED.value(),
            HttpStatus.UNAUTHORIZED.getReasonPhrase(),
            authException.getMessage(), version, applicationName, Instant.now(), request.getRequestURI());
         log.error(authException.getMessage());
         ObjectMapper mapper = new ObjectMapper();
         response.setStatus(HttpStatus.UNAUTHORIZED.value());
         response.setContentType("application/json");
         response.setCharacterEncoding("UTF-8");
         response.getWriter().write(mapper.writeValueAsString(status));
    }
}

扩展
用户名密码身份验证筛选器时,可以自定义其
身份验证失败处理程序
,当
尝试身份验证()
抛出
身份验证异常
时将调用该处理程序

AuthenticationFailureHandler
看起来像:

public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler{

    @Override
    public void onAuthenticationFailure(HttpServletRequest request,
            HttpServletResponse response, AuthenticationException exception)
            throws IOException, ServletException {


         RESTFulStatus status = new RESTFulStatus(RESTFulStatus.STATUS_ERROR, HttpStatus.UNAUTHORIZED.value(),
            HttpStatus.UNAUTHORIZED.getReasonPhrase(),
            authException.getMessage(), version, applicationName, Instant.now(), request.getRequestURI());
         log.error(exception.getMessage());
         ObjectMapper mapper = new ObjectMapper();
         response.setStatus(HttpStatus.UNAUTHORIZED.value());
         response.setContentType("application/json");
         response.setCharacterEncoding("UTF-8");
         response.getWriter().write(mapper.writeValueAsString(status));
    }

}
注:

  • 确保
    attemptAuthentication()
    将引发
    AuthenticationException
    如果身份验证失败
  • 确保将此自定义的
    AuthenticationFailureHandler
    设置为
    jwtusername和passwordauthenticationfilter
    配置期间
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler{

    @Override
    public void onAuthenticationFailure(HttpServletRequest request,
            HttpServletResponse response, AuthenticationException exception)
            throws IOException, ServletException {


         RESTFulStatus status = new RESTFulStatus(RESTFulStatus.STATUS_ERROR, HttpStatus.UNAUTHORIZED.value(),
            HttpStatus.UNAUTHORIZED.getReasonPhrase(),
            authException.getMessage(), version, applicationName, Instant.now(), request.getRequestURI());
         log.error(exception.getMessage());
         ObjectMapper mapper = new ObjectMapper();
         response.setStatus(HttpStatus.UNAUTHORIZED.value());
         response.setContentType("application/json");
         response.setCharacterEncoding("UTF-8");
         response.getWriter().write(mapper.writeValueAsString(status));
    }

}