ChatGPT解决这个技术问题 Extra ChatGPT

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

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

XMLHttpRequest 无法加载 http://server.apiurl.com:8000/s/login?login=facebook。对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问源“http://localhost”。错误 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 的标头。

困惑:您是“配置服务器”还是这是“亚马逊网络服务上的休息 api”?
您显然还没有做足够的工作来在服务器端启用 CORS。发布响应标头示例
无论哪种方式,您的反对票都是错误的。他在他的本地机器上托管他的文件。他在后端做什么样的conf都没有关系。 Angular 不允许这种预飞行。
感谢评论,当我将浏览器设置为关闭安全性时它起作用了
@Andre但是关闭安全性只是一个丑陋的解决方法,您会损害安全性,并不能解决您的问题...

E
E. Maggini

您遇到了 CORS 问题。

有几种方法可以解决/解决此问题。

关闭 CORS。例如:如何在 chrome 中关闭 cors 为您的浏览器使用插件 使用 nginx 等代理。如何设置的示例 完成服务器的必要设置。这更多是您在 EC2 实例上加载的 Web 服务器的一个因素(假设这就是您所说的“Amazon Web 服务”)。对于您的特定服务器,您可以参考启用 CORS 网站。

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

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

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

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

绕过 CORS 正是那些只学习前端的人所展示的。 https://codecraft.tv/courses/angular/http/http-with-promises/


谢谢你拯救了我的一天。仅使用第一个选项:C:\Program Files (x86)\Google\Chrome\Application>chrome.exe --user-data-dir="C:\Chrome dev session" --disable-web-security。来自:stackoverflow.com/questions/3102819/…
在浏览器中禁用cors?这不是一个解决方案,它是一种解决方法,对真正需要启用 CORS 的人没有帮助。
@JonathanSimas 如前所述,这是继续开发工作的几种方法之一。变通方法是解决方案。您甚至会在我的回答中注意到,我说这安全性很差,真的只是把罐子踢到了路上。 ;-)
你至少应该提到有一个在许多情况下是合适的解决方案,即设置 CORS。如果你这样做,将不再有反对票
关闭 chrome 中的 cors 或 chrome 中的插件从来没有真正的解决方案(如果网站有 CORS 问题,您会要求每个客户在此之前禁用他们的 CORS?)。感谢您的回复,但我希望您将这两点标记为假解决方案。真正的解决方案是配置 WS/API 以允许允许的来源
h
hutchonoid

我的“API 服务器”是一个 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');

我同意,这比接受的答案要好,尽管在复制这些行时要小心,确保修改方法和来源。
将它放在 Angular 6 项目中的什么位置?
@CodyBugstein 和 whatthefish 放在任何输出之前
@whatthefish 这是服务器端更改,而不是客户端更改。
@AsmaRahimAliJafri 这必须在服务器端完成!
A
ArieKanarie

在 AspNetCore web api 中,通过添加“Microsoft.AspNetCore.Cors”(版本 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")] 放在控制器上。


如果您想构建跨站点脚本漏洞,这是一个很好的答案!请永远不要这样做!指定您可以访问的域以避免安全问题。 CORS 的存在是有原因的。
只是为了更清楚@paqogomez,在您的 ConfigureServices 方法中: services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", builder => { builder.WithOrigins("localhost") .AllowAnyOrigin() .AllowAnyHeader () .AllowAnyMethod(); }); }); 并在您的配置方法中:app.UseCors("AllowSpecificOrigin");
S
Sasa Blagojevic

关于 CORS,有一些注意事项。首先,它不允许使用通配符 *,但不要让我坚持我在某处读过它,但现在找不到这篇文章。

如果您从其他域发出请求,则需要添加允许来源标头。

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

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

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

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

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

max-age 标头很重要,在我的情况下,没有它就无法工作,我猜浏览器需要“访问权限”有效时间的信息。

此外,如果您使用来自不同域的 application/json mime 发出例如 POST 请求,您还需要添加前面提到的 allow origin 标头,因此它看起来像这样:

   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

当飞行前成功并获得所有需要的信息时,您的实际请求将被提出。

一般来说,无论是在初始请求或飞行前请求中请求的任何 Access-Control 标头,都应在响应中给出以使其正常工作。

this link 上的 MDN 文档中有一个很好的示例,您还应该查看 this SO post


这是 Mozilla 文章,讨论如何不能将通配符用于 cors 来源:Link 显然这仅适用于使用凭据时(如果我理解正确的话)
我正在使用通配符并提交一个不记名令牌来授权请求并且它工作正常,所以不确定我上面提供的链接是指关于凭据的什么。我的问题是,在 .Net Core 中构建我的 CORS 策略时,我没有添加 .AllowCredentials()。添加 .AllowCredentials() 后一切正常。
f
freedev

如果您正在编写 chrome 扩展

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

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

还要检查你是否有 www 前缀
这是一个救命稻草,因为关于扩展/插件的文档非常有限
T
Tadej

JavaScript XMLHttpRequest 和 Fetch 遵循同源策略。因此,使用 XMLHttpRequest 或 Fetch 的 Web 应用程序只能向其自己的域发出 HTTP 请求。

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

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

如果您使用 Apache 作为您的 HTTP 服务器,那么您可以将其添加到您的 Apache 配置文件中,如下所示:

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

Mod_headers 在 Apache 中默认启用,但是,您可能希望通过运行以下命令来确保它已启用:

 a2enmod headers

我在哪里可以找到我的 Apache 配置文件?
@ShubhamArya 在 linux Debian 上的默认位置是:/etc/apache2/apache2.conf
我在哪里可以在 windows 中找到它?
@Shubham Arya:Windows 默认位置是 C:\Program Files\Apache\Apache2\conf\httpd.conf ,您可以在 httpd.apache.org/docs/2.0/platform/windows.xml 中找到更多详细信息
a
atiruz

在 PHP 中,您可以添加标题:

<?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: *");
...

谢谢,它对我有用!在测试和生产环境中。即使使用 https://
@atiruz 感谢您的解决方案。这在我添加行 header ("Access-Control-Expose-Headers: Content-Length, X-JSON"); 时有效
L
Lucio

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

npm i cors

只需将以下几行添加到 app.js

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

这仅适用于 express js 应用程序,并非所有节点应用程序
非 Express js 应用程序的任何解决方案?
@iprashant 看看 cors lib 在做什么并做同样的事情。
@AntiCZ 无需查看 cors .. 看看它如何使用 cors 作为中间件 .. 通过 cors api 路由您的所有请求......然后到您的实际 api ......
S
Sunil Kumar

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

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

有了所有这些帖子,获取等,都可以正常工作。


T
Teriblus

对于 python flask server,你可以使用 flask-cors 插件来启用跨域请求。

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


w
w00ngy

我们的团队偶尔会使用 Vue、axios 和 C# WebApi 看到这一点。在您尝试命中的端点上添加路由属性可以为我们修复它。

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

我们不确定为什么。哈哈。如果有人告诉我!
X
Xu Chen

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

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

我还想插话并提到一个我不认为 AWS 文件的大问题。假设您使用 API 网关代理您的 lambda 函数,并且您在该 lambda 函数中使用了一些 API。如果该 API 返回非 200 成功成功代码并且您没有将非 200 成功代码添加到 API 网关中的方法响应中,那么您将收到错误并且看不到您的成功响应。示例:Sendgrid 和 Twilio 有非 200 成功代码。
T
TrieuNomad

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

您需要明确定义路由方法才能使 CORS 正常工作。

https://i.stack.imgur.com/hwmy3.png

希望这在 AWS Docs for Configuring CORS for an HTTP API 中更明确

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

希望这篇文章可以为那些使用 Api Gateway HTTP API 的人节省一些时间和精力。


这正是我的问题。谢谢!
h
hugsbrugs

在我的 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 ^(.*)$ $1 [R=200,L]

S
Shubham Pandey

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

所以最好在你的后端修复。

首先在标题中,您需要设置-

header('Access-Control-Allow-Origin: *');

header('标头集 Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"');

如果 API 的行为既是 GET 又是 POST ,那么还要在你的标题中设置 -

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']}");退出(0); }


C
Christian Oliver

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


我在我的服务器中正确实现了 CORS,但我忘记添加 PUT 方法
s
sastorsl

跨域资源共享 (CORS) 是一种基于 HTTP 标头的机制,它允许服务器指示除其自身之外的任何来源(域、方案或端口),浏览器应允许从这些来源加载资源

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

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

Scammysite.bad 试图告诉你的浏览器向 good-api-site.good 发送请求 good-api-site.good 告诉你的浏览器它应该只信任 other-good-site.good 你的浏览器说你真的不应该信任scammysite.bad 对 good-api-site.good 的请求和去 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=$0
# 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>

K
Kirill Husiatyn

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


d
davyCode

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

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

F
Fiach Reid

https://i.stack.imgur.com/AO86o.png

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

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


M
Mr Lister

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

从 webapps/geoserver/WEB-INF/web.xml 取消注释以下 <filter><filter-mapping>

<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>

这并没有在响应头中添加 antyhing,所以它没有用
没有使用 GeoServer,但这个剪辑帮助我了解了我应该在接收呼叫的应用程序上使用的设置。
R
Rahul sah

只需几个步骤即可轻松解决此问题,无需担心任何事情。请按照步骤解决。

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


var express = require('express') var cors = require('cors') var app = express() app.use(cors()) app.get('/products/:id', function (req, res, next) { res.json({msg: '这是为所有来源启用 CORS!'}) }) app.listen(80, function () { console.log('CORS 启用的 Web 服务器在端口 80 上侦听' ) })
在我看来,这也仅在快速节点应用程序中有效,而在其他任何应用程序中均无效。
m
mauricio

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

Access-Control-Allow-Methods: GET, OPTIONS

但是!再次,这适用于 Chrome、Firefox,但遗憾的是不适用于 Chromium


P
Pavel

对预检请求的响应未通过访问控制检查正是问题所在:

在发出实际的 GET 请求之前,浏览器会检查服务是否为 CORS 正确配置。这是通过检查服务是否接受实际请求将使用的方法和标头来完成的。因此,仅允许从不同来源访问服务是不够的,还必须满足其他要求。

将标题设置为

Header always set Access-Control-Allow-Origin: www.example.com 
Header always set Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS 
Header always set Access-Control-Allow-Headers: Content-Type #etc...

是不够的。您必须添加重写规则:

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

链接到 great read


W
Wes

很容易错过的东西...

在解决方案资源管理器中,右键单击 api-project。在属性窗口中将“匿名身份验证”设置为已启用!!!


N
Nithin

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