如何将CORS头添加到BasicErrorController呈现的Spring错误页面?

时间:2017-04-18 04:46:02

标签: spring spring-mvc spring-boot

我有一个单页客户端由Spring Boot REST MVC API应用程序(spring boot version 1.5.2)提供服务。

我的应用程序通过Auth0 JWT令牌保护。当事情正常时,响应的CORS标头由ServletFilter提供,它被配置为设置安全性的一部分:

  protected void configure(HttpSecurity http) throws Exception {
    ...
    http.addFilterBefore(simpleCORSFilter(), Auth0AuthenticationFilter.class);
    ...
  }

这似乎在我到目前为止测试过的任何地方都有用 - 但是它无法正常工作的地方是默认的Spring错误页面(路径" / error",由默认为BasicErrorController类。

当我的服务方法中出现异常时,错误页面工作并在响应正文中呈现我想要的内容作为JSON,但客户端应用程序无法访问http响应正文,因为响应缺少CORS标头。

所以问题是:"如何将CORS标题添加到错误页面"?

我应该从安全设置中删除CORS过滤器并更全面地应用CORS过滤器吗?这将在哪里完成 - 我无法在Spring文档中找到任何相关内容。

或者我应该编写自定义错误控制器?文档中唯一的自定义错误控制器示例似乎允许您返回一个字符串。

2 个答案:

答案 0 :(得分:1)

您可以为错误定义一个单独的Controller,并允许使用

跨越原点
@CrossOrigin("*")

答案 1 :(得分:0)

将Poorvi的回答与Joni Karppinen的custom error controller代码结合起来给出了:

@RestController
public class ErrorController 
implements org.springframework.boot.autoconfigure.web.ErrorController 
{
  private static final String PATH = "/error";

  @Autowired private ErrorAttributes errorAttributes;

  @Override
  public String getErrorPath(){
    return PATH;
  }

  // I guess when time comes to lock down cors header, we could use a spring 
  // value configuration here to share with corsfilter.
  @CrossOrigin("*")  
  @RequestMapping(value = PATH, produces = "application/json")
  public @ResponseBody
  ErrorJson error(HttpServletRequest request, HttpServletResponse response){
    return new ErrorJson(
      response.getStatus(), 
      getErrorAttributes(request, false) );
  }

  private Map<String, Object> getErrorAttributes(
    HttpServletRequest request,
    boolean includeStackTrace
  ){
    RequestAttributes requestAttributes = new ServletRequestAttributes(request);
    return errorAttributes.getErrorAttributes(
      requestAttributes,
      includeStackTrace);
  }  

}

class ErrorJson {

  public Integer status;
  public String error;
  public String message;
  public String timeStamp;
  public String trace;

  public ErrorJson(int status, Map<String, Object> errorAttributes){
    this.status = status;
    this.error = (String) errorAttributes.get("error");
    this.message = (String) errorAttributes.get("message");
    this.timeStamp = errorAttributes.get("timestamp").toString();
    this.trace = (String) errorAttributes.get("trace");
  }

}

这似乎对我有用。