Spring Boot 和 PreFlight 请求

Posted

技术标签:

【中文标题】Spring Boot 和 PreFlight 请求【英文标题】:Spring Boot and PreFlight requests 【发布时间】:2018-04-13 18:08:49 【问题描述】:

我正在使用Spring Boot version 2.0.0.M5

我的javascript 应用程序在调用我暴露的 Rest 端点时遇到问题。 为了安全起见 - 我希望传入一个包含 api 密钥的标头。 但是 - 预检请求(选项)没有设置标头

以下JavaScriptsn-p 为我重现了错误

var baseEndpoint = "http://localhost:8480";
var data = null; 
var xhr = new XMLHttpRequest(); 
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () 
  if (this.readyState === 4) 
    console.log(this.responseText);
  
);
xhr.open("GET", baseEndpoint + "/api/issue/user/1");
xhr.setRequestHeader("x-api-key", "fdarwetr5467hyyerf");
xhr.setRequestHeader("cache-control", "no-cache");
xhr.setRequestHeader("Accept","application/json");
xhr.setRequestHeader("Content-Type","application/json");
xhr.setRequestHeader("Origin", "localhost");
xhr.send(null);

即使我得到它是一个 OPTIONS 请求 - x-api-key 标头也不会通过

我在 Spring Boot 中的 cors 设置如下

@Override
public void addCorsMappings(CorsRegistry corsRegistry) 
    super.addCorsMappings(corsRegistry);
    corsRegistry.addMapping("/**").allowedMethods("*").allowedOrigins("*").exposedHeaders("x-api-key", "apiKey").allowedHeaders("x-api-key", "apiKey").allowCredentials(true);      

我想知道处理这些预检请求的正确方法是什么?或者有没有人有任何建议让标题通过?

【问题讨论】:

【参考方案1】:

我通过在所有 api 请求上添加过滤器解决了这个问题 当请求方法为 OPTIONS 时——我刚刚成功退出过滤器

    if ("OPTIONS".equals(request.getMethod())) 
        response.setStatus(HttpServletResponse.SC_OK);
        return super.preHandle(request, response, handler);
    

【讨论】:

您需要在您的应用程序中打开所有选项请求吗? 我没有..没有特别需要这样做 您不需要为此使用自定义过滤器。您可以扩展 WebSecurityConfigurerAdapter 配置类,只需覆盖 void configure(WebSecurity web) 里面只需调用 web.ignoring().antMathers(HttpMethod.OPTIONS, "/**");

以上是关于Spring Boot 和 PreFlight 请求的主要内容,如果未能解决你的问题,请参考以下文章

[CORS][Spring Security] PreFlight 请求未处理

preflight request预检请求

Angular 的 Spring Cloud Gateway Preflight Cors 错误

Angular 6 - Spring MVC :: Options preflight request throws 500 internal Server Error

Spring Kafka和Spring Boot整合实现消息发送与消费简单案例

导致 PREFLIGHT 的 HTTP 标头 - 澄清?