![](/img/trans.png)
[英]Is there a way to handle an exception thrown from inside of custom exception handler in Spring?
[英]Java Spring Boot Custom Exception Handler thrown out of controller
我試圖在“unsuccessfulAuthentication”中拋出我的自定義異常,問題是我無法在我的全局異常處理程序中捕獲它。 就像控制器(服務)調用的控制器和類拋出的異常沒有被全局異常處理程序捕獲。
我的身份驗證過濾器
package com.ekahau.booking.security;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.ekahau.booking.exception.UnAuthorizedException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE;
@Slf4j
public class CustomAuthFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authManager;
public CustomAuthFilter(AuthenticationManager authManager) {
this.authManager = authManager;
}
@Override
protected void unsuccessfulAuthentication(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException failed
) throws IOException, ServletException {
response.setContentType(APPLICATION_JSON_VALUE);
System.out.println("------------------------------");
System.out.println("------------------------------");
System.out.println("------------------------------");
System.out.println("------------------------------");
throw new UnAuthorizedException("Invalid Credentials");
// super.unsuccessfulAuthentication();
// Map<String, String> errorResponse = new HashMap<>();
// errorResponse.put("timestamp", (new Date().toString()));
// errorResponse.put("status", HttpStatus.UNAUTHORIZED.toString());
// errorResponse.put("message", "Invalid credentials");
//Add more descriptive message
// response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed");
// new ObjectMapper().writeValue(response.getOutputStream(), errorResponse);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
String username = request.getParameter("username");
String password = request.getParameter("password");
log.info("Username: {} with password: {} attempted to login", username, password);
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
username,
password
);
return authManager.authenticate(authToken);
}
@Override
protected void successfulAuthentication(
HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authentication
) throws IOException, ServletException {
var user = (UserDetails) authentication.getPrincipal();
var algo = Algorithm.HMAC256("secret".getBytes());
var claim = user.
getAuthorities().
stream().
map(GrantedAuthority::getAuthority).collect(Collectors.toList());
var accessToken = JWT.create()
.withSubject(user.getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + 2 * 60 * 60 * 1000 ))
.withIssuer(request.getRequestURL().toString())
.withClaim("roles", claim)
.sign(algo);
var refreshToken = JWT.create()
.withSubject(user.getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + 12 * 60 * 60 * 1000 ))
.withIssuer(request.getRequestURL().toString())
.withClaim("roles", claim)
.sign(algo);
// return token in the response body
response.setContentType(APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
/* old fashion way
response.getWriter().write(String.format(
"{\"access_token\":\"%s\", \"refresh_token\":\"%s\"", accessToken, refreshToken
));*/
Map<String, String> tokens = new HashMap<>();
tokens.put("access_token", accessToken);
tokens.put("refresh_token", refreshToken);
new ObjectMapper().writeValue(response.getOutputStream(), tokens);
/*
return token in the headers
response.set("access_token", accessToken);
response.setHeader("refresh_token", refreshToken);
*/
}
}
我的全局異常處理程序:
/***
* @param ex the ex
* @param request the request
* @return the response entity
*/
@ExceptionHandler(UnAuthorizedException.class)
public ResponseEntity<?> handleUnAuthorizedException(
UnAuthorizedException ex, WebRequest request) {
ErrorResponse errorDetails =
new ErrorResponse(
new Date(),
HttpStatus.UNAUTHORIZED.toString(),
ex.getMessage(),
request.getDescription(false),
null
);
return new ResponseEntity<>(errorDetails, HttpStatus.UNAUTHORIZED);
}
和我完整的全局異常處理程序:
package com.ekahau.booking.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@ControllerAdvice
@RestControllerAdvice
public class GlobalExceptionHandler {
/***
* @param ex the ex
* @param request the request
* @return the response entity
*/
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<?> handleResourceNotFoundException(
ResourceNotFoundException ex, WebRequest request) {
ErrorResponse errorDetails =
new ErrorResponse(
new Date(),
HttpStatus.NOT_FOUND.toString(),
ex.getMessage(),
request.getDescription(false),
null
);
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}
/***
* @param ex the ex
* @param request the request
* @return the response entity
*/
@ExceptionHandler(UnAuthorizedException.class)
public ResponseEntity<?> handleUnAuthorizedException(
UnAuthorizedException ex, WebRequest request) {
ErrorResponse errorDetails =
new ErrorResponse(
new Date(),
HttpStatus.UNAUTHORIZED.toString(),
ex.getMessage(),
request.getDescription(false),
null
);
return new ResponseEntity<>(errorDetails, HttpStatus.UNAUTHORIZED);
}
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<?> handleConstraintViolationException(
ConstraintViolationException ex,
WebRequest request) {
Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
var errors = new HashMap<String, Set<String>>();
constraintViolations.forEach(violation -> {
var messages = new HashSet<String>();
messages.add(String.format(
"%s value '%s' %s",
violation.getPropertyPath(),
violation.getInvalidValue(),
violation.getMessage()));
errors.put(violation.getPropertyPath().toString(), messages);
});
ErrorResponse errorDetails =
new ErrorResponse(
new Date(),
HttpStatus.NOT_FOUND.toString(),
"Validation Exception",
request.getDescription(false),
errors
);
return new ResponseEntity<>(errorDetails, HttpStatus.UNPROCESSABLE_ENTITY);
}
/**
* Validation exception handler
*
* @param ex the ex
* @param request the request
* @return the response entity
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex,
WebRequest request
) {
final List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
Map<String, Set<String>> errorsMap = fieldErrors.stream().collect(
Collectors.groupingBy(FieldError::getField,
Collectors.mapping(FieldError::getDefaultMessage, Collectors.toSet())
)
);
ErrorResponse errorDetails =
new ErrorResponse(
new Date(),
HttpStatus.UNPROCESSABLE_ENTITY.toString(),
ex.getMessage() + " exception class : " + ex.getClass(),
request.getDescription(false),
(HashMap<String, Set<String>>) errorsMap
);
return new ResponseEntity<>(errorDetails, HttpStatus.UNPROCESSABLE_ENTITY);
}
/**
* Globle excpetion handler response entity.
*
* @param ex the ex
* @param request the request
* @return the response entity
*/
@ExceptionHandler(Exception.class)
public ResponseEntity<?> handleGlobleExcpetionHandler(Exception ex, WebRequest request) {
ErrorResponse errorDetails =
new ErrorResponse(
new Date(),
HttpStatus.INTERNAL_SERVER_ERROR.toString(),
ex.getMessage() + " exception class : " + ex.getClass(),
request.getDescription(false),
null
);
return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
您應該會發現以下問題/答案對解決您的查詢很有用:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.