java - Spring:如何使过滤器抛出自定义异常?

标签 java spring

我创建了一个过滤器来验证 JWT token 的每个请求 header :

public class JWTAuthenticationFilter extends GenericFilterBean {

    private UserDetailsService customUserDetailsService;
    private static Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
    private final static UrlPathHelper urlPathHelper = new UrlPathHelper();

    public JWTAuthenticationFilter(UserDetailsService customUserDetailsService) {
        this.customUserDetailsService = customUserDetailsService;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        Authentication authentication = AuthenticationService.getAuthentication((HttpServletRequest) request, customUserDetailsService);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        if (authentication == null) {
            logger.debug("failed authentication while attempting to access " + urlPathHelper.getPathWithinApplication((HttpServletRequest) request));
        }
        filterChain.doFilter(request, response);
    }

}

我想抛出一个自定义异常,该异常返回一个响应:

@ResponseStatus(value=HttpStatus.SOMECODE, reason="There was an issue with the provided authentacion information")  // 409
public class CustomAuthenticationException extends RuntimeException {

    private static final long serialVersionUID = 6699623945573914987L;

}

我应该怎么做?捕获过滤器抛出的此类异常的最佳设计是什么? 是否有 Spring 安全性提供的任何类型的异常处理机制,我可以使用并一次性捕获所有内容? 有没有其他方法可以在过滤器中抛出自定义异常?

注意:还有一个问题here它接受的答案没有回答我的问题。我想在到达任何 Controller 之前返回响应。

我想处理的错误情况: 1. 客户端为 Authorization header 发送一个空值。 2.客户端发送格式错误的 token

在这两种情况下,我都会收到带有 500 HTTP 状态代码的响应。我想取回 4XX 代码。

最佳答案

看看@ControllerAdvice

这是我项目中的一个示例。

@ControllerAdvice
@RestController
public class GlobalExceptionHandler {

    private final Logger log = Logger.getLogger(this.getClass().getSimpleName());

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = RuntimeException.class)
    public Response handleBaseException(RuntimeException e) {
        log.error("Error", e);
        Error error = new Error(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name());
        return Response.status(HttpStatus.BAD_REQUEST.value()).error(error, null).build();
    }

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(value = NoHandlerFoundException.class)
    public Response handleNoHandlerFoundException(Exception e) {
        log.error("Error", e);
        Error error = new Error(HttpStatus.NOT_FOUND.value(), HttpStatus.NOT_FOUND.name());
        return Response.status(HttpStatus.NOT_FOUND.value()).error(error, null).build();
    }

    @ExceptionHandler(value = AuthenticationCredentialsNotFoundException.class)
    public Response handleException(AuthenticationCredentialsNotFoundException e) {     
        log.error("Error", e);
        Error error = new Error(ErrorCodes.INVALID_CREDENTIALS_CODE, ErrorCodes.INVALID_CREDENTIALS_MSG);
        return Response.status(ErrorCodes.INVALID_CREDENTIALS_CODE).error(error, null).build();
    }

    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(value = UnauthorisedException.class)
    public Response handleNotAuthorizedExceptionException(UnauthorisedException e) {        
//      log.error("Error", e);
        return Response.unauthorized().build();
    }

    @ExceptionHandler(value = Exception.class)
    public String handleException(Exception e) {
        log.error("Error", e);
        return e.getClass().getName() + " 14" + e.getMessage();
    }


}

编辑

我相信你可以在 do Filter 方法中使用 response.sendError。

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
    Authentication authentication = AuthenticationService.getAuthentication((HttpServletRequest) request, customUserDetailsService);
    SecurityContextHolder.getContext().setAuthentication(authentication);
    if (authentication == null) {
        logger.debug("failed authentication while attempting to access " + urlPathHelper.getPathWithinApplication((HttpServletRequest) request));
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid authentication.");
        setUnauthorizedResponse(response);
        return;
    }
    filterChain.doFilter(request, response);
}

public void setUnauthorizedResponse(HttpServletResponse response) {
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    response.setContentType("application/json");
    Response unAuthorizedResponse = Response.unauthorized().build();
    try {
        PrintWriter out = response.getWriter();
        out.println(unAuthorizedResponse.toJsonString());
    } catch (IOException e) {
        log.error("Error", e);
    }
}

关于java - Spring:如何使过滤器抛出自定义异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44040703/

相关文章:

java - spring boot 2 embed tomcat 9.0.26 无法加载jks文件流关闭

java - Android 字符串加密/解密

java - Junit 5 集成测试 Docker

java - 从我的 java 代码使用基本 http 身份验证的服务器下载文件时出现问题

java - Spring数据cassandra CrudRepository保存问题: some messages are not getting inserted

spring - 在 MongoDB for Spring 中查找/删除 @DBref 列表项

java - spring validator 中如何获取请求参数?

spring - Grails 3 和 LDAP 身份验证

java - 按下键盘上的完成时如何不关闭键盘

java - 如何提高 java 应用程序从 oracle 数据库中获取大数据的性能?