为什么我的 JavaScript 代码收到“请求的资源上不存在'Access-Control-Allow-Origin'标头”错误,而 Postman 没有?

Why does my JavaScript code receive a "No 'Access-Control-Allow-Origin' header is present on the requested resource" error, while Postman does not?

提问人:Mr Jedi 提问时间:11/18/2013 最后编辑:pizzaisdavidMr Jedi 更新时间:7/30/2023 访问量:6188526

问:

Mod 说明:这个问题是关于为什么浏览器上的 //etc. 受到相同访问策略限制(您收到提及 CORB 或 CORS 的错误),而 Postman 则不受限制。这个问题不是关于如何解决“没有'访问-控制-允许-起源'......”的问题。错误。这是关于它们发生的原因。XMLHttpRequestfetch

请停止发帖

  • 适用于每种语言/框架的 CORS 配置。相反,找到相关语言/框架的问题
  • 允许请求规避 CORS 的第三方服务
  • 用于关闭各种浏览器的 CORS 的命令行选项

我正在尝试通过连接到 RESTful API 内置 Flask 来使用 JavaScript 进行授权。但是,当我提出请求时,出现以下错误:

XMLHttpRequest cannot load http://myApiUrl/login. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'null' is therefore not allowed access.

我知道 API 或远程资源必须设置标头,但为什么当我通过 Chrome 扩展程序 Postman 发出请求时它能正常工作?

这是请求代码:

$.ajax({
  type: 'POST',
  dataType: 'text',
  url: api,
  username: 'user',
  password: 'pass',
  crossDomain: true,
  xhrFields: {
    withCredentials: true,
  },
})
  .done(function (data) {
    console.log('done');
  })
  .fail(function (xhr, textStatus, errorThrown) {
    alert(xhr.responseText);
    alert(textStatus);
  });
javascript jquery cors postman 同源策略

评论

56赞 MD. Sahib Bin Mahboob 11/18/2013
您是从 localhost 发出请求还是直接执行 HTML?
2赞 Mr Jedi 11/18/2013
@MD.SahibBinMahboob 如果我理解您的问题,我会从 localhost 请求 - 我的计算机上有页面并运行它。当我在托管上部署站点时,它给出了相同的结果。
16赞 Sam Eaton 6/18/2015
对于任何想要了解更多阅读内容的人,MDN 有一篇关于 ajax 和跨域请求的好文章:developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
1赞 Peter Mortensen 10/4/2021
这个问题的答案(现已删除,仅对 10K 人可见)是元问题的主题:为什么这个被点赞的答案被删除了一次,并在重新发布时再次删除?
0赞 OG Sean 6/23/2022
相关的 CORS 深入研究了相同的错误,但要与 S3 / Cloudfront 触发它的缓存和标头有关,也在此处:stackoverflow.com/questions/44800431/...

答:

1660赞 MD. Sahib Bin Mahboob 11/18/2013 #1

如果我理解正确的话,您正在对与您的页面所在的域不同的域执行 XMLHttpRequest。因此,浏览器阻止了它,因为出于安全原因,它通常允许同一来源的请求。当您想要执行跨域请求时,您需要执行一些不同的操作。

当您使用 Postman 时,它们不受此策略的限制。引自跨域 XMLHttpRequest

常规网页可以使用 XMLHttpRequest 对象从远程服务器发送和接收数据,但它们受到同源策略的限制。扩展没有那么有限。扩展可以与其源之外的远程服务器通信,只要它首先请求跨域权限即可。

评论

249赞 Ray Nicholus 11/18/2013
浏览器未阻止请求。唯一完全阻止跨域 ajax 请求的浏览器是 IE7 或更早版本。除 IE7 及更早版本外,所有浏览器都实现了 CORS 规范(IE8 和 IE9 部分)。您需要做的就是通过根据请求返回正确的标头来选择加入 API 服务器上的 CORS 请求。您应该阅读 mzl.la/VOFrSz 上的 CORS 概念。Postman 也通过 XHR 发送请求。如果您在使用 postman 时没有看到同样的问题,这意味着您在不知不觉中没有通过 postman 发送相同的请求。
21赞 Ray Nicholus 11/18/2013
@MD.SahibBinMahboob Postman 不会发送“来自 java/python”代码的请求。它直接从浏览器发送请求。Chrome 扩展程序中的 XHR 工作方式确实略有不同,尤其是在涉及跨域请求时
1赞 Rayed 3/24/2023
在这篇文章上找到了一个详细的例子:stackoverflow.com/questions/66486610/...
0赞 trainoasis 9/13/2023
只有当某些请求参数等于 10 rofl 时,我们才会在本地发生?适用于所有其他方案。这到底是怎么回事?:D
365赞 Shady Mohamed Sherif 12/4/2014 #2

警告:使用可以使您的 API/网站容易受到跨站请求伪造 (CSRF) 攻击。在使用此代码之前,请确保您了解风险Access-Control-Allow-Origin: *

如果您使用的是 PHP,则解决起来非常简单。只需在处理请求的 PHP 页面的开头添加以下脚本:

<?php header('Access-Control-Allow-Origin: *'); ?>

如果您使用的是 Node-red,则必须通过取消注释以下行来允许文件中的 CORSnode-red/settings.js

// The following property can be used to configure cross-origin resource sharing
// in the HTTP nodes.
// See https://github.com/troygoode/node-cors#configuration-options for
// details on its contents. The following is a basic permissive set of options:
httpNodeCors: {
  origin: "*",
  methods: "GET,PUT,POST,DELETE"
},

如果您使用的 Flask 与问题相同;您必须先安装flask-cors

pip install -U flask-cors

然后,在应用程序中包含 Flask cors 包。

from flask_cors import CORS

一个简单的应用程序将如下所示:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

有关更多详细信息,您可以查看 Flask 文档

评论

240赞 user229044 12/30/2014
你不应该关闭 CORS,因为你不知道它的用途。这会使用户处于根本上不安全的状态。
182赞 ZurabWeb 2/27/2015
尽管它可能不安全,但问题不在于安全性,而在于如何完成任务。这是开发人员在处理跨域 AJAX 请求时必须选择的选项之一。它帮助我解决了这个问题,对于我的应用程序,我不在乎数据来自哪里。我用PHP清理了目标域上的所有输入,所以,如果有人想向它发布一些垃圾,让他们试试。这里的要点是,可以允许来自目标域的跨域 AJAX。+1 答案。
5赞 shruti 9/29/2021
@meagar 同意你的观点,我们不应该关闭 CORS,但有时我们需要在开发应用程序时测试它,为此,最简单的方法是关闭 CORS 并检查是否一切正常。很多时候,前端开发人员无法访问后端系统,他们可以在其中更改内容,或者他们需要为此编写代理。添加 chrome 扩展程序以关闭 CORS 以进行开发的最佳方法,如已删除的答案中所写。
1赞 Eve 12/1/2021
如果答案(或顶部带有警告的编辑)可以解释如果在 php 中使用该 header() 脚本,对谁有风险,那应该会很有帮助。这里的问题是关于我们无法控制的外国站点,它只允许我们从浏览器导航和查看它,而如果我们需要从我们的服务器访问资源,它会启动 CORS 保护(不要让我们每秒进行太多查询)。因此,我的问题仍然存在,如果在我们的服务器中使用 header() 脚本,我们访问者有什么危险?编辑是否将访客(我们)与主持人混淆了?
1赞 Eve 12/10/2021
@ShadyMohamedSherif,从历史上看,曾经有一段时间,人们被允许以任何方式(浏览器、应用程序等)“消费”在 IP 上/通过某个端口/暴露的网站,并且在滥用事件发生后,网站所有者开始限制浏览器只能连接到他们的页面?换句话说,当人们只是缓慢地请求一个网页(在浏览器上)时。我的意思是,即使是 ddos 也不能通过浏览器发生,这里不谈论其他狡猾的方法来查询可能存在的网站内容
106赞 George 12/13/2016 #3

因为
$.ajax({type: “POST” - 调用 OPTIONS
$.post( - 调用 POST

两者都是不同的。Postman 正确地调用“POST”,但当我们调用它时,它将是“OPTIONS”。

对于 C# Web 服务 - Web API

请在 web.config 文件中的 <system.webServer> 标记下添加以下代码。这将起作用:

<httpProtocol>
    <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
    </customHeaders>
</httpProtocol>

请确保您在 Ajax 调用中没有犯任何错误。

jQuery的

$.ajax({
    url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    type: "POST", /* or type:"GET" or type:"PUT" */
    dataType: "json",
    data: {
    },
    success: function (result) {
        console.log(result);
    },
    error: function () {
        console.log("error");
    }
});

注意:如果您正在寻找从第三方网站下载内容,那么这对您没有帮助。您可以尝试以下代码,但不能尝试 JavaScript。

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");
80赞 Kamil Kiełczewski 12/16/2019 #4

在下面作为 API 的调查中,我使用 http://example.com 而不是从您的问题中 http://myApiUrl/login,因为第一个有效。我假设您的页面已 http://my-site.local:8088

注意:API 和您的页面具有不同的域!

您看到不同结果的原因是 Postman:

  • set header(您的 API)Host=example.com
  • NOT 设置标头Origin
  • Postman 实际上根本不使用您的网站 url(您只在 Postman 中输入您的 API 地址) - 他只向 API 发送请求,因此他假设网站与 API 具有相同的地址(浏览器不假设这一点)

这类似于浏览器在站点和 API 具有相同域时发送请求的方式(浏览器也设置了标头项,但我在 Postman 中没有看到它)。设置 Origin 标头时,通常服务器默认允许此类请求。Referer=http://my-site.local:8088

Enter image description here

这是 Postman 发送请求的标准方式。但是,当您的网站和 API 具有不同的域时,浏览器会以不同的方式发送请求,然后发生 CORS,浏览器会自动:

  • 设置标头(作为 API)Host=example.com
  • 设置标头(您的网站)Origin=http://my-site.local:8088

(标头的值与 相同。现在,在Chrome的“控制台和网络”选项卡中,您将看到:RefererOrigin

Enter image description here

Enter image description here

当您拥有 Host != Origin 时,这是 CORS,当服务器检测到此类请求时,它通常会默认阻止它

Origin=null当您从本地目录打开 HTML 内容并发送请求时设置。同样的情况是,当您在 中发送请求时,如下面的代码片段(但此处根本没有设置标头) - 一般来说,只要 HTML 规范说 opaque origin,您都可以将其转换为 .您可以在此处找到有关此内容的更多信息。<iframe>HostOrigin=null

fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab

如果您不使用简单的 CORS 请求,通常浏览器在发送主请求之前也会自动发送 OPTIONS 请求 - 更多信息在这里。下面的代码片段显示了它:

fetch('http://example.com/api', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)

您可以更改服务器的配置以允许 CORS 请求。

这是一个在nginx(nginx.conf文件)上打开CORS的示例配置--在nginx和Apache的设置时要非常小心-这将从任何域中取消阻止CORS(在生产中,而不是星号使用使用你的具体页面广告,它消耗你的api)always/"$http_origin""*"

location ~ ^/index\.php(/|$) {
   ...
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    if ($request_method = OPTIONS) {
        add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        return 204;
    }
}

下面是在 Apache 上打开 CORS 的示例配置(.htaccess 文件)

# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests                                                 |
# ------------------------------------------------------------------------------

# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/

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

# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"

Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"

评论

10赞 Nam G VU 2/19/2022
很棒,解释得很好,很容易赶上!谢谢!
1赞 Ray Jasson 1/3/2023
这个答案清楚地证明了这个评论所描述的内容:。干的好!If you are not seeing the same problem when using postman, this means that you are unknowingly not sending the same request via postman
0赞 Noam 9/29/2023
这个答案似乎有些误导。虽然服务器可能会阻止“主机”和“源”不同的请求,但它也可能不会。但只要它没有明确发送标头告诉可以完成请求,浏览器就会阻止它以保护用户。Postman 中不存在这种保护,因为它具有不同的目的和不同的条件。
45赞 Gopinath 2/2/2020 #5

应用 CORS 限制是由服务器定义并由浏览器实现的安全功能。

浏览器查看服务器的 CORS 策略并遵守它。

但是,Postman 工具不会为服务器的 CORS 策略而烦恼。

这就是为什么CORS错误出现在浏览器中,而不是Postman中的原因。

39赞 JacquesB 1/10/2021 #6

您遇到的错误是由于 CORS 标准造成的,该标准对 JavaScript 如何执行 ajax 请求设置了一些限制。

CORS 标准是在浏览器中实现的客户端标准。因此,阻止调用完成并生成错误消息的是浏览器,而不是服务器。

Postman 未实现 CORS 限制,这就是为什么在从 Postman 进行相同调用时看不到相同的错误。

为什么 Postman 不实现 CORS?CORS 定义了与发起请求的页面的源(URL 域)相关的限制。但在 Postman 中,请求不是来自具有 URL 的页面,因此 CORS 不适用。

评论

8赞 JacquesB 1/11/2021
@MrJedi:接受的答案没有解释为什么请求在 Postman 中成功,这是最初的问题。
0赞 Eve 12/1/2021
服务器最初旨在将流发送到客户端(浏览器软件程序),而不是发送到各种桌面或服务器应用程序,而是以扭曲的方式运行。浏览器与服务器建立握手协议,接收有关连接的确认,然后恢复数据流。在某些情况下,机器人农场服务器发送了数百万个查询,并且主机将许多资源(打开的进程)提交到这些最终从未发生的停滞连接中的每一个,从而阻止了其响应其他合法请求的能力
0赞 JacquesB 10/28/2022
@Eve:CORS 是在浏览器中实现的客户端措施,因此不能阻止来自机器人场的 DDOS 攻击。
2赞 Aris 12/1/2022
这实际上是最好的解释,也是意识到 CORS 是浏览器标准的“啊哈时刻”!
6赞 NDM 12/9/2021 #7

如果网关超时时间太短,并且所访问的资源的处理时间比超时长,则也可能收到此错误。对于复杂的数据库查询等,可能会出现这种情况。因此,上面的错误代码可以掩盖这个问题。只需检查错误代码是否是 504 而不是 Kamil 的答案中的 404 或其他内容。如果是 504,则增加网关超时可能会解决问题。

在我的情况下,可以通过在 Internet Explorer 浏览器中禁用同源策略 (CORS) 来消除 CORS 错误,请参阅如何禁用同源策略 Internet Explorer这样做之后,日志中出现了纯 504 错误。

评论

0赞 Mr Jedi 12/10/2021
如果 gettimeout,则不会收到 CORS 错误
0赞 NDM 12/13/2021
好吧,我确实对系统进行了故障排除,而 CORS 错误让我失望了,只是超时时间太短,导致连接关闭。增加超时后,系统运行良好。所以是的,超时导致了“无”访问控制允许-起源“错误,这让我首先进入了这个线程。因此,这可能对其他人将其与 504 一起扔掉有所帮助。
0赞 Mr Jedi 12/15/2021
这更确切地说意味着您的应用程序配置有问题。超时时不应出现此错误
1赞 ogie 8/23/2022
在我的情况下,当 nginx 超时时时,我还遇到了一个令人困惑的 CORS 504 错误。增加超时使服务重新联机,而不会出现 CORS 错误。谢谢你的提示。
17赞 Stas Sorokin 1/3/2022 #8

解决方案和问题起源

您正在向不同的域发出 XMLHttpRequest,例如:

  1. 领域一:some-domain.com
  2. 领域二:some-different-domain.com

域名的这种差异触发了称为 SOP同源策略)的 CORS跨域资源共享)策略,该策略强制在 Ajax、XMLHttpRequest 和其他 HTTP 请求中使用相同的域(因此是 Origin)。

为什么当我通过 Chrome 扩展程序发出请求时它能正常工作 邮差?

客户端(大多数浏览器开发工具)可以选择强制执行同源策略。

大多数浏览器都执行同源策略,以防止与CSRF跨站点请求伪造)攻击相关的问题。

Postman 作为一种开发工具,选择不强制执行 SOP,而某些浏览器强制执行,这就是为什么您可以通过 Postman 发送请求,而您不能使用浏览器通过 JS 使用 XMLHttpRequest 发送请求。

7赞 Daniel Iftimie 1/10/2022 #9

出于浏览器测试目的:

Windows - 运行:

chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security

上面的命令将禁用 chrome 网络安全。因此,例如,如果您在本地项目上工作并在尝试发出请求时遇到 CORS 策略问题,则可以使用上述命令跳过此类错误。基本上,它将打开一个新的chrome会话。

评论

1赞 ZebraCoder 6/21/2022
你能解释一下吗?
3赞 Daniel Iftimie 6/23/2022
@ZebraCoder 上述命令将禁用 chrome 网络安全。因此,例如,如果您在本地项目上工作并在尝试发出请求时遇到 CORS 策略问题,则可以使用上述命令跳过此类错误。基本上,它将打开一个新的chrome会话。
0赞 Peter Mortensen 9/5/2022
你能把信息添加到答案本身吗?评论可能随时被删除。(但是 **************** 没有 *************** “编辑:”、“更新:”或类似 - 答案应该看起来像今天写的一样)
1赞 Bapan Biswas 2/14/2022 #10

您的 IP 地址未列入白名单,因此您会收到此错误。 要求后端工作人员将您正在访问的服务的 IP 地址列入白名单。

Access-Control-Allow-Headers 访问控制允许标头

3赞 lunarzshine 4/14/2022 #11

若要解决此问题,请在后端使用的 或 函数中编写此代码行doGet()doPost()

response.setHeader("Access-Control-Allow-Origin", "*");

您可以输入访问网站的网站或 API URL 端点,否则它将是公开的。"*"

-6赞 Shohedul 8/11/2022 #12

它通过在全球范围内应用这个中间件对我有用:

<?php

    namespace App\Http\Middleware;

    use Closure;

    class Cors {
       public function handle($request, Closure $next) {
           return $next($request)
                   ->header('Access-Control-Allow-Origin', '*')
                   ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
                   ->header('Access-Control-Allow-Headers', "Accept,authorization,Authorization, Content-Type");
       }
    }

评论

1赞 Peter Mortensen 9/5/2022
“在全球范围内应用这个中间件”是什么意思?你能详细说明一下吗?
1赞 Peter Mortensen 9/5/2022
这如何回答这个问题?该问题用 JavaScriptjQueryCORS 标记。如果是这样,应该解释一下。该类的名称为“Cors”,但这有什么关系呢?要点是什么?
1赞 DINA TAKLIT 11/28/2022 #13

对我来说,我出于不同的原因遇到了这个问题,远程域已添加到源中,部署的应用程序运行良好,除了一个端点我遇到了这个问题:

Origin https://mai-frontend.vercel.app is not allowed by Access-Control-Allow-Origin. Status code: 500

Fetch API cannot load https://sciigo.herokuapp.com/recommendations/recommendationsByUser/8f1bb29e-8ce6-4df2-b138-ffe53650dbab due to access control checks.

我发现我的 Heroku 数据库表不包含本地表的所有列,更新 Heroku 数据库表后一切正常。

2赞 Pranav MS 4/12/2023 #14

可以通过在服务器的 web.config 文件中添加以下脚本来允许 CORS

<system.webServer>
     <httpProtocol>
         <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Methods" value="*" />
            <add name="Access-Control-Allow-Headers" value="*" />
         </customHeaders>
     </httpProtocol>
</system.webServer>
-3赞 Anmol Pal 7/30/2023 #15

如果您使用 Node.js (Express.js) 构建后端,请尝试使用npm i cors

....
const cors = require("cors");
.....

app.use(cors());
...

评论

1赞 dragonx 8/5/2023
这并不能回答这个问题。