已被CORS政策阻止:对预检请求的响应未通过访问控制检查

GGG*_*GGG 18 go axios

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

has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.
Run Code Online (Sandbox Code Playgroud)

我们对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)
   });
} 
Run Code Online (Sandbox Code Playgroud)

我的文件:

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))
}
Run Code Online (Sandbox Code Playgroud)

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

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

Rya*_*ton 23

这个答案解释了幕后发生的事情,以及如何用任何语言解决这个问题的基础知识。如需参考,请参阅有关此主题的 MDN 文档

您正在从一个域(例如 domain-a.com)上运行的 JavaScript 向另一个域(domain-b.com)上运行的 API 发出对 URL 的请求。当你这样做时,浏览器必须询问 domain-b.com 是否允许来自 domain-a.com 的请求。它通过 HTTPOPTIONS请求来实现。然后,在响应中,域 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
Run Code Online (Sandbox Code Playgroud)

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

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

header := w.Header()
header.Add("Access-Control-Allow-Origin", "*")

if r.Method == "OPTIONS" {
    w.WriteHeader(http.StatusOK)
    return
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这是一个非常深入的答案,并成功解释了 CORS 错误的通常原因 (3认同)

Eri*_* Fu 21

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

  1. AWS HTTP API 网关;
  2. 您正在使用带有身份验证的任何方法来进行路由和 lambda 集成;
  3. 您认为您已正确配置 CORS;

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

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


thr*_*eve 13

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

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, Access-Control-Allow-Headers, Authorization, X-Requested-With")
Run Code Online (Sandbox Code Playgroud)

您还可以为添加标题Access-Control-Max-Age,当然也可以允许任何所需的标题和方法。

最后,您想响应初始请求:

if r.Method == "OPTIONS" {
    w.WriteHeader(http.StatusOK)
    return
}
Run Code Online (Sandbox Code Playgroud)

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

以下是旧的中间件建议: 当然,为此使用中间件可能会更容易。我不认为我已经用它,但是这一次似乎来得强烈推荐。


小智 9

在 ASP.NET Web API 中启用跨域请求点击了解更多信息

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

Install-Package Microsoft.AspNet.WebApi.Cors
Run Code Online (Sandbox Code Playgroud)

此命令安装最新的包并更新所有依赖项,包括核心 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 }
            );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

接下来,将 [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...
    }
}
Run Code Online (Sandbox Code Playgroud)

在 ASP.NET Core 中启用跨域请求 (CORS)

  • +1 正确,OP 指定了 Go lang,但我来到这里并需要一个针对 aspnet 的解决方案,这对我有帮助 (3认同)

Sat*_*hia 8

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

  1. C:\Program Files\Google\Chrome\Application

  2. 打开命令提示符

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

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

在此处输入图片说明

  • 不确定,但在 2023 年,我还发现这是唯一适合我的解决方案。 (3认同)

7gu*_*uyo 5

Angular 和 Django Rest 框架。

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