簡體   English   中英

Java Spring 啟動自定義異常處理程序拋出 controller

[英]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);
    }
}

您應該會發現以下問題/答案對解決您的查詢很有用:

使用 @ControllerAdvice 制作簡單的 servlet 過濾器

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM