Spring AuthenticationEntryPoint 返回 Tomcat HTML 错误而不是 JSON

Posted

技术标签:

【中文标题】Spring AuthenticationEntryPoint 返回 Tomcat HTML 错误而不是 JSON【英文标题】:Spring AuthenticationEntryPoint returns Tomcat HTML error instead of JSON 【发布时间】:2018-03-03 02:25:15 【问题描述】:

我正在使用 Spring 在更大的应用程序中公开 API。当访问位于 authenticated() 配置后面的端点时,我的应用程序会因为以下代码而抛出一个丑陋的 Tomcat html 错误:

@Component
public class EntryPointUnauthorizedHandler implements AuthenticationEntryPoint 

    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
            AuthenticationException e) throws IOException, ServletException 
        httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Access Denied");
    

但是,由于这是一个 API,我只想返回 JSON,就像我的 API 的其余部分一样。对于正常的异常处理,我设置了以下@ControllerAdvice

@ControllerAdvice
public class DefaultExceptionHandler extends ResponseEntityExceptionHandler 

    /**
     * Default internal BadCredentialsException handler. Respond with 401 Unauthorized
     */
    @ExceptionHandler(value = BadCredentialsException.class)
    public ResponseEntity<Object> handleBadCredentialsException(BadCredentialsException e, WebRequest request) 
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return handleExceptionInternal(e, null, headers, HttpStatus.UNAUTHORIZED, request);
    

    /**
     * Fallback default exception handler. Respond with 500
     */
    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<Object> handleFallbackException(Exception e, WebRequest request) 
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return handleExceptionInternal(e, null, headers, HttpStatus.INTERNAL_SERVER_ERROR, request);
    

    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body,
            HttpHeaders headers, HttpStatus status, WebRequest request) 

        final ErrorResponse error = new ErrorResponse(status, ex.getMessage());

        if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) 
            request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
        

        return new ResponseEntity<Object>(error, headers, status);
    

ErrorResponse 是我自己的小响应包装器,其中包含 HttpStatus 代码和异常消息。这被格式化为 JSON 格式:


    "status": 401,
    "message": "Bad credentials"

我如何确保我的AuthenticationEntryPoint 只有一个请求和响应对象才能返回类似格式的错误,而不是丑陋的 Tomcat HTML 页面。

【问题讨论】:

Handle spring security authentication exceptions with @ExceptionHandler的可能重复 【参考方案1】:

您可以根据需要更改HttpServletResponse。 看一看:https://***.com/a/19788700/1490806

【讨论】:

手动编写 JSON 字符串或使用 ObjectMapper 感觉非常丑陋和 hacky。真的没有合适的方法来做到这一点吗?感觉就像我错误地使用了 Spring。如果您需要在此 AuthenticationEntryPoint 中再次执行此操作,那么在 1 个位置定义您的异常处理有什么意义? spring 安全过滤器发生在 spring dispatcher servlet 之前。所以我猜春天无法控制安全过滤器链上发生的异常。 visola.github.io/img/blog/spring-security-architecture.png我不知道有其他方法可以做到这一点。

以上是关于Spring AuthenticationEntryPoint 返回 Tomcat HTML 错误而不是 JSON的主要内容,如果未能解决你的问题,请参考以下文章

Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC

学习笔记——Spring简介;Spring搭建步骤;Spring的特性;Spring中getBean三种方式;Spring中的标签

Spring--Spring入门

Spring框架--Spring事务管理和Spring事务传播行为

Spring框架--Spring事务管理和Spring事务传播行为

Spring框架--Spring JDBC