对预检请求的响应未通过访问控制检查

Response to preflight request doesn't pass access control check

我在使用 ngResource 调用 Amazon Web Services 上的 REST API 时遇到此错误:

XMLHttpRequest cannot load http://server.apiurl.com:8000/s/login?login=facebook. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. Error 405

服务:

socialMarkt.factory('loginService', ['$resource', function ($resource) {
    var apiAddress = "http://server.apiurl.com:8000/s/login/";
    return $resource(apiAddress, {
        login: "facebook",
        access_token: "@access_token",
        facebook_id: "@facebook_id"
    }, {
        getUser: {
            method: 'POST'
        }
    });
}]);

控制器:

[...]
loginService.getUser(JSON.stringify(fbObj)),
    function (data) {
        console.log(data);
    },
    function (result) {
        console.error('Error', result.status);
    }
[...]

我正在使用 Chrome,但我不知道还能做些什么来解决这个问题。我什至将服务器配置为接受来自 localhost.

的 headers

您 运行 遇到 CORS 问题。

有几种方法可以fix/workaround这个。

  1. 关闭 CORS。例如:how to turn off cors in chrome
  2. Use a plugin for your browser
  3. 使用代理,例如 nginx。 example of how to set up
  4. 完成服务器的必要设置。这更多是您在 EC2 实例上加载的 Web 服务器的一个因素(假设这就是您所说的“Amazon Web 服务”)。对于您的特定服务器,您可以参考 enable CORS website.

更详细地说,您正在尝试从本地主机访问 api.serverurl.com。这就是跨域请求的确切定义。

通过关闭它只是为了完成你的工作(好吧,但是如果你访问其他网站并且只是把罐头踢到路上对你来说安全性很差)或者你可以使用代理让你的浏览器考虑所有当您确实有本地服务器然后调用远程服务器时,请求来自本地主机。

所以 api.serverurl.com 可能会变成 localhost:8000/api 并且您的本地 nginx 或其他代理将发送到正确的目的地。


现在应大众需求,100% more CORS info..同样美味!


对于单纯学习前端的人来说,绕过CORS正是其中的内容。 https://codecraft.tv/courses/angular/http/http-with-promises/

我的 "API Server" 是一个 PHP 应用程序,所以为了解决这个问题,我发现以下解决方案有效:

将行放在 index.php

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');

对于pythonflask server,可以使用flask-cors插件开启跨域请求。

参见:https://flask-cors.readthedocs.io/en/latest/

我在 DNS 服务器设置为 8.8.8.8 (google's) 时遇到过这个问题。实际上,问题出在路由器上,我的应用程序试图通过 google 连接服务器,而不是在本地(对于我的特殊情况)。我删除了 8.8.8.8,这解决了问题。 我知道这个问题可以通过 CORS 设置解决,但也许有人会遇到和我一样的麻烦

在我的 Apache VirtualHost 配置文件中,我添加了以下几行:

Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$  [R=200,L]

JavaScript XMLHttpRequest and Fetch follow the same-origin policy. So, a web application using XMLHttpRequest or Fetch could only make HTTP requests to its own domain.

来源:https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

您必须从服务器端发送 Access-Control-Allow-Origin: * HTTP header。

如果您使用 Apache 作为您的 HTTP 服务器,那么您可以像这样将它添加到您的 Apache 配置文件中:

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
</IfModule>

Mod_headers 在 Apache 中默认启用,但是,您可能希望通过 运行:

确保它已启用
 a2enmod headers

在 AspNetCore web api 中,通过添加 "Microsoft.AspNetCore.Cors"(ver 1.1.1)并在 Startup.cs.

上添加以下更改解决了这个问题
public void ConfigureServices(IServiceCollection services)
{ 
    services.AddCors(options =>
    {
          options.AddPolicy("AllowAllHeaders",
                builder =>
            {
                    builder.AllowAnyOrigin()
                           .AllowAnyHeader()
                           .AllowAnyMethod();
                });
    });
    .
    .
    .
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{


    // Shows UseCors with named policy.
    app.UseCors("AllowAllHeaders");
    .
    .
    .
}

并将[EnableCors("AllowAllHeaders")]放在控制器上。

很容易错过的东西...

在解决方案资源管理器中,右键单击 api-项目。在属性 window 中将 'Anonymous Authentication' 设置为启用 !!!

如果您正在编写 chrome-extension

您必须在 manifest.json 中添加您域的权限。

"permissions": [
   "http://example.com/*",
   "https://example.com/*",
   "http://www.example.com/*",
   "https://www.example.com/*"
]

如果您偶然使用 IIS 服务器。您可以在 HTTP 请求 headers 选项中设置下面的 headers。

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: 'HEAD, GET, POST, PUT, PATCH, DELETE'
Access-Control-Allow-Headers: 'Origin, Content-Type, X-Auth-Token';

所有 post、get 等都可以正常工作。

对于那些正在使用 Lambda 集成代理和 API 网关。您需要像直接向它提交请求一样配置您的 lambda 函数,这意味着该函数应该正确设置响应 headers。 (如果您使用自定义 lambda 函数,这将由 API 网关处理。)

//In your lambda's index.handler():
exports.handler = (event, context, callback) => {
     //on success:
     callback(null, {
           statusCode: 200,
           headers: {
                "Access-Control-Allow-Origin" : "*"
           }
     }
}

在 PHP 中您可以添加 headers:

<?php
header ("Access-Control-Allow-Origin: *");
header ("Access-Control-Expose-Headers: Content-Length, X-JSON");
header ("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
header ("Access-Control-Allow-Headers: *");
...

GeoServer 的独立发行版包括 Jetty 应用程序服务器。启用跨源资源共享 (CORS) 允许 JavaScript 您自己域外的应用程序使用 GeoServer。

取消注释 webapps/geoserver/WEB-INF/web 中的以下 <filter><filter-mapping>。xml:

<web-app>
  <filter>
      <filter-name>cross-origin</filter-name>
      <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>cross-origin</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

我认为 从 Chrome 禁用 CORS 不是好方法,因为如果你在 ionic 中使用它,肯定会在 Mobile Build 中再次出现问题。

最好在您的后端进行修复。

首先在header中,你需要设置-

  • header('Access-Control-Allow-Origin: *');
  • header('Header set Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"');

并且如果 API 的行为与 GET 和 POST 一样,那么也会在您的 header-

中设置

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) header("Access-Control-Allow-Headers:
{$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); exit(0); }

禁用 chrome security.Create chrome 快捷方式 右键单击 -> 属性 -> 目标,粘贴此 "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="c:/chromedev"

我正在使用 AWS sdk 进行上传,在花了一些时间在线搜索后我偶然发现了这个线程。感谢@lsimoneau 45581857 事实证明发生了完全相同的事情。我只是通过附加区域选项将我的请求 Url 指向我存储桶上的区域并且它起作用了。

 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: 'eu-west-2'  // add region here });

此错误的一个非常常见的原因可能是主机 API 已将请求映射到 http 方法(例如 PUT)并且 API 客户端正在调用 API使用不同的 http 方法(例如 POST 或 GET)

修复 Node JS 应用程序中的跨源请求问题:

npm i cors

只需将下面的行添加到 app.js

let cors = require('cors')
app.use(cors())

关于 CORS,有一些注意事项。首先,它不允许使用通配符 * 但不要让我在这个问题上停下来,我已经在某处读过它,但现在找不到这篇文章了。

如果您从不同的域发出请求,您需要添加允许来源 header。

 Access-Control-Allow-Origin: www.other.com 

如果您正在发出影响服务器资源的请求,例如 POST/PUT/PATCH,并且如果 mime 类型不同于以下 application/x-www-form-urlencodedmultipart/form-datatext/plain浏览器将自动发出 pre-flight OPTIONS 请求以检查服务器是否允许。

因此您的 API/server 需要相应地处理这些 OPTIONS 请求,您需要使用适当的 access control headers 进行响应并且 http 响应状态代码需要为 200.

header应该是这样的,根据您的需要调整它们:

   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

max-age header 很重要,在我的例子中,没有它就无法工作,我想浏览器需要 "access rights" 有效期的信息。

此外,如果您正在制作例如来自不同域的带有 application/json mime 的 POST 请求您还需要添加前面提到的允许来源 header,因此它看起来像这样:

   Access-Control-Allow-Origin: www.other.com 
   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

当 pre-flight 成功并获得所有需要的信息时,您的实际请求就会发出。

一般来说,无论 Access-Control header 在初始请求或 pre-flight 请求中请求什么,都应在响应中给出以使其正常工作。

this link, and you should also check out this SO post

上的 MDN 文档中有一个很好的示例

我们的团队偶尔会看到使用 Vue、axios 和 C# WebApi 的情况。在您尝试访问的端点上添加路由属性为我们修复了它。

[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }

这个问题很简单,简单几步就可以解决,不用担心任何事情。 请按照步骤解决。

  1. 打开 (https://www.npmjs.com/package/cors#enabling-cors-pre-flight)
  2. 转到安装并复制命令 npm install cors 以通过节点终端安装
  3. 通过scrolling.then复制和粘贴转到简单使用(启用所有 CORS 请求) 你项目中的完整声明和 运行 它......肯定会起作用...... 复制评论代码并粘贴到你的 app.js 或任何其他项目中并试一试..这将 work.this 将解锁每个跨源资源共享..因此我们可以在服务之间切换供您使用

对于任何使用 Api 网关的 HTTP API 和代理路由的人 ANY /{proxy+}

为了让 CORS 工作,您需要明确定义路由方法。

希望这在 AWS Docs for Configuring CORS for an HTTP API

中更明确

与 AWS Support 进行了 2 小时的通话,他们联系了一位高级 HTTP API 开发人员,他提出了这个建议。

希望这个 post 可以为那些使用 Api 网关 HTTP API.

的人节省一些时间和精力

使用API网关中的Cors选项,我使用了上面显示的以下设置

另请注意,您的函数必须 return HTTP 状态 200 以响应 OPTIONS 请求,否则 CORS 也会失败。

Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading of resources

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

简而言之 - 网络服务器 告诉您(您的浏览器)您应该信任哪些站点来使用 那个 站点。

  1. Scammysite.bad 试图告诉您的浏览器向 good-api-site.good[= 发送请求53=]
  2. good-api-site.good 告诉你的浏览器它应该只信任 other-good-site.good
  3. 你的浏览器说你真的不应该相信 scammysite.badgood-api-[=78= 的请求] CORS 救了你

如果您正在创建 一个站点,并且您真的不在乎谁与您集成。继续耕种。在您的 ACL 中设置 *

但是如果您正在创建站点,并且只允许站点 X,甚至站点 X、Y 和 Z,您使用 CORS 来 指示客户端浏览器 只信任这些站点与 您的 站点集成。

浏览器当然可以选择忽略这个。同样,CORS 保护的是您的客户,而不是您。

CORS 允许 * 一个 站点定义。这可能会限制您,但您可以通过向 Web 服务器添加一些动态配置来解决这个问题 - 帮助您做到具体。

这是关于如何在 Apache 中配置 CORS pr 站点的示例:

# Save the entire "Origin" header in Apache environment variable "AccessControlAllowOrigin"
# Expand the regex to match your desired "good" sites / sites you trust
SetEnvIfNoCase Origin "^https://(other-good-site\.good|one-more-good.site)$" AccessControlAllowOrigin=[=10=]
# Assuming you server multiple sites, ensure you apply only to this specific site
<If "%{HTTP_HOST} == 'good-api-site.com'">
    # Remove headers to ensure that they are explicitly set
    Header        unset Access-Control-Allow-Origin   env=AccessControlAllowOrigin
    Header        unset Access-Control-Allow-Methods  env=AccessControlAllowOrigin
    Header        unset Access-Control-Allow-Headers  env=AccessControlAllowOrigin
    Header        unset Access-Control-Expose-Headers env=AccessControlAllowOrigin
    # Add headers "always" to ensure that they are explicitly set
    # The value of the "Access-Control-Allow-Origin" header will be the contents saved in the "AccessControlAllowOrigin" environment variable
    Header always set Access-Control-Allow-Origin   %{AccessControlAllowOrigin}e     env=AccessControlAllowOrigin
    # Adapt the below to your use case
    Header always set Access-Control-Allow-Methods  "POST, GET, OPTIONS, PUT"        env=AccessControlAllowOrigin
    Header always set Access-Control-Allow-Headers  "X-Requested-With,Authorization" env=AccessControlAllowOrigin
    Header always set Access-Control-Expose-Headers "X-Requested-With,Authorization" env=AccessControlAllowOrigin
</If>

我成功了,将 OPTIONS 方法添加到 Access-Control-Allow-Methods

Access-Control-Allow-Methods: GET, OPTIONS

但是!同样,这在 Chrome、Firefox 中有效,但遗憾的是在 Chromium

中无效