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