【问题标题】:Has been blocked by CORS policy: Response to preflight request doesn’t pass access control check已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查
【发布时间】:2019-04-17 07:37:26
【问题描述】:

我已经创建了旅行服务器。它工作正常,我们可以通过 Insomnia 发出 POST 请求,但是当我们在前端通过 axios 发出 POST 请求时,它会发送错误:

has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.

我们对 axios 的要求:

let config = {
headers: {
  "Content-Type": "application/json",
  'Access-Control-Allow-Origin': '*',
  }
}

let data = {
  "id": 4
 }

 axios.post('http://196.121.147.69:9777/twirp/route.FRoute/GetLists', data, config)
   .then((res) => {
      console.log(res)
     })
    .catch((err) => {
      console.log(err)
   });
} 

我的 go 文件:

func setupResponse(w *http.ResponseWriter, req *http.Request) {
    (*w).Header().Set("Access-Control-Allow-Origin", "*")
    (*w).Header().Set("Access-Control-Allow-Methods", "POST,GET,OPTIONS, PUT, DELETE")

    (*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}


func WithUserAgent(base http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

    ctx := r.Context()
    ua := r.Header.Get("Jwt")
    ctx = context.WithValue(ctx, "jwt", ua)

    r = r.WithContext(ctx)

    setupResponse(&w, r)
     base.ServeHTTP(w, r)
  })
}

const (
    host     = "localhost"
    port     = 5432
    user     = "postgres"
    password = "postgres"
    dbname   = "postgres"
)

func main() {

    psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
           "password=%s dbname=%s sslmode=disable",
               host, port, user, password, dbname)

    server := &s.Server{psqlInfo}

    twirpHandler := p.NewFinanceServiceServer(server, nil)

    wrap := WithUserAgent(twirpHandler)
      log.Fatalln(http.ListenAndServe(":9707", wrap))
}

正如我之前在 Insomnia 上所说的,它工作得很好,但是当我们发出 axios POST 请求时,浏览器的控制台上会出现以下内容:

已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态。

【问题讨论】:

  • (*w).Header().Set("Access-Control-Allow-Origin", req.Header.Get("Origin"))
  • @mkopriva 不起作用(
  • 请参考这篇文章的答案以及如何解决这个问题stackoverflow.com/questions/53528643/…
  • 嗨,Ramesh,该链接可能不是您要粘贴的链接,它似乎是您对与 spring 和框架的特定 CrossOrigin 过滤器有关的问题的回答。对于它的价值,我认为对于这个问题,如果您看到 prefilght 请求但它抱怨状态不正确,那么根据我的经验,您要么在响应之前发生另一个错误,要么不允许使用 OPTIONS动词。

标签: rest google-chrome go axios cors


【解决方案1】:

我相信这是最简单的例子:

header := w.Header()
header.Add("Access-Control-Allow-Origin", "*")
header.Add("Access-Control-Allow-Methods", "DELETE, POST, GET, OPTIONS")
header.Add("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")

您还可以为Access-Control-Max-Age 添加标头,当然您可以允许任何您希望的标头和方法。

最后你要响应初始请求:

if r.Method == "OPTIONS" {
    w.WriteHeader(http.StatusOK)
    return
}

编辑(2019 年 6 月):我们现在为此使用 gorilla。他们的东西得到了更积极的维护,而且他们已经这样做了很长时间。留下旧链接,以防万一。

下面的旧中间件推荐: 当然,为此使用中间件可能会更容易。我不认为我用过它,但 this one 似乎受到强烈推荐。

【讨论】:

    【解决方案2】:

    应该在后端修复 CORS 问题。 临时解决方法使用此选项。

    1. 打开命令提示符

    2. 导航到 chrome 安装位置 OR 输入 cd "c:\Program Files (x86)\Google\Chrome\Application" OR cd "c:\Program Files\Google\Chrome\Application"

    3. 执行命令chrome.exe --disable-web-security --user-data-dir="c:/ChromeDevSession"

    使用上述选项,您可以打开没有安全性的新 chrome。这个 chrome 不会引发任何 cors 问题。

    【讨论】:

    • 这是唯一对我有用的东西。其他解决方案均无效。
    • @johnstaveley,感谢您的赞赏。
    【解决方案3】:

    对于尚未找到解决方案的任何人,如果您正在使用:

    1. AWS HTTP API 网关;
    2. 您正在使用 ANY Method with Authentication 进行路由和 lambda 集成;
    3. 您认为您已正确配置 CORS;

    该错误是因为浏览器正在向您的路由发送预检 OPTIONS 请求而没有 Authentication 标头,因此无法获取 CORS 标头作为响应。

    为了解决这个问题,我为没有身份验证的 OPTIONS 方法添加了另一个路由,并且 lambda 集成只返回 { statusCode: 200 };

    【讨论】:

      【解决方案4】:

      对于查看此内容但添加 Access-Control-Allow-Origin 没有结果的任何人,请尝试添加 Access-Control-Allow-Headers。可以使某人免于头痛。

      【讨论】:

        【解决方案5】:

        唯一对我有用的是在 IIS 中创建一个新应用程序,将其映射到完全相同的物理路径,并且仅将身份验证更改为匿名。

        【讨论】:

        • 比我幸运。没有任何效果,尽管以下应该有效! app.UseCors(builder => { builder .AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); });
        【解决方案6】:

        Angular 和 Django Rest 框架。

        我在向我的 DRF api 发出发布请求时遇到了类似的错误。 碰巧我所缺少的只是端点的尾部斜杠

        【讨论】:

        • 我刚刚用了 1 个小时(Vue.js + Django Rest Framework)
        【解决方案7】:

        这里提供的解决方案是正确的。但是,用户错误也可能发生相同的错误,即您的端点请求方法与发出请求时使用的方法不匹配。

        例如,当您将方法请求为 POST 时,使用“RequestMethod.PUT”定义服务器端点。

        【讨论】:

          【解决方案8】:

          这个答案解释了幕后发生的事情,以及如何用任何语言解决这个问题的基础知识。如需参考,请参阅the MDN docs on this topic

          您正在从一个域(例如 domain-a.com)上运行的 JavaScript 向另一个域(domain-b.com)上运行的 API 发出 URL 请求。当您这样做时,浏览器必须询问 domain-b.com 是否可以允许来自 domain-a.com 的请求。它通过 HTTP OPTIONS 请求来实现。然后,在响应中,domain-b.com 上的服务器必须(至少)提供以下 HTTP 标头,上面写着“是的,没关系”:

          HTTP/1.1 204 No Content                            // or 200 OK
          Access-Control-Allow-Origin: https://domain-a.com  // or * for allowing anybody
          Access-Control-Allow-Methods: POST, GET, OPTIONS   // What kind of methods are allowed
          ...                                                // other headers
          

          如果您使用的是 Chrome,您可以通过按 F12 并转到“网络”选项卡查看 domain-b.com 上的服务器给出的响应来查看响应。

          所以,回到@threeve 的原始答案的最低限度:

          header := w.Header()
          header.Add("Access-Control-Allow-Origin", "*")
          
          if r.Method == "OPTIONS" {
              w.WriteHeader(http.StatusOK)
              return
          }
          

          这将允许任何人从任何地方访问这些数据。由于其他原因,他包含的其他标头是必需的,但这些标头是通过 CORS(跨源资源共享)要求的最低要求。

          【讨论】:

          • 实际上,转到“网络”选项卡不会告诉您任何信息。即使控制台选项卡显示存在跨域标头错误,GET 显然也会成功。 this answer 对此进行了解释。
          • 我认为您正在查看 OPTIONS 请求,而不是 GET 请求。对于您在代码中执行的每个 GET 请求,Chrome 的“网络”选项卡中应该有 2 个请求。
          • 这是一个非常深入的答案,并设法解释了 CORS 错误的原因通常是什么
          【解决方案9】:

          Enable cross-origin requests in ASP.NET Web API点击了解更多信息

          在 WebService 应用中启用 CORS。首先,添加 CORS NuGet 包。在 Visual Studio 中,从工具菜单中选择 NuGet 包管理器,然后选择包管理器控制台。在包管理器控制台窗口中,键入以下命令:

          Install-Package Microsoft.AspNet.WebApi.Cors
          

          此命令会安装最新的包并更新所有依赖项,包括核心 Web API 库。使用 -Version 标志来定位特定版本。 CORS 包需要 Web API 2.0 或更高版本。

          打开文件 App_Start/WebApiConfig.cs。将以下代码添加到 WebApiConfig.Register 方法中:

          using System.Web.Http;
          namespace WebService
          {
              public static class WebApiConfig
              {
                  public static void Register(HttpConfiguration config)
                  {
                      // New code
                      config.EnableCors();
          
                      config.Routes.MapHttpRoute(
                          name: "DefaultApi",
                          routeTemplate: "api/{controller}/{id}",
                          defaults: new { id = RouteParameter.Optional }
                      );
                  }
              }
          }
          

          接下来,将 [EnableCors] 属性添加到您的控制器/控制器方法中

          using System.Net.Http;
          using System.Web.Http;
          using System.Web.Http.Cors;
          
          namespace WebService.Controllers
          {
              [EnableCors(origins: "http://mywebclient.azurewebsites.net", headers: "*", methods: "*")]
              public class TestController : ApiController
              {
                  // Controller methods not shown...
              }
          }
          

          Enable Cross-Origin Requests (CORS) in ASP.NET Core

          【讨论】:

          • op 指定的 Go 语言
          • Go lang 或 axios 不是 C#
          • +1 是的,OP 指定了 Go 语言,但我来到这里并需要一个针对 aspnet 的解决方案,这对我有帮助
          猜你喜欢
          • 2019-12-14
          • 1970-01-01
          • 2020-09-30
          • 2019-10-22
          • 2019-04-11
          • 2022-07-01
          • 2020-01-23
          • 2019-11-18
          相关资源
          最近更新 更多