ChatGPT解决这个技术问题 Extra ChatGPT

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

Mod note:这个问题是关于为什么 XMLHttpRequest/fetch/etc.浏览器上的受相同访问策略限制(您会收到提及 CORB 或 CORS 的错误),而 Postman 则不受此限制。这个问题不是关于如何修复“No 'Access-Control-Allow-Origin'...”错误。这是关于它们发生的原因。

请停止发帖:日光下每种语言/框架的 CORS 配置。而是找到您的相关语言/框架的问题。允许请求绕过 CORS 的第 3 方服务 用于关闭各种浏览器的 CORS 的命令行选项

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

XMLHttpRequest 无法加载 http://myApiUrl/login。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'null' 不允许访问。

我知道 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);
  });
您是从 localhost 发出请求还是直接执行 HTML?
@MD.SahibBinMahboob 如果我理解您的问题,我会从本地主机请求 - 我的计算机上有页面并运行它。当我在托管上部署站点时,它给出了相同的结果。
对于希望阅读更多内容的人,MDN 有一篇关于 ajax 和跨源请求的好文章:developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
此问题的答案(现已删除,仅对 10K'ers 可见)是元问题 Why was this upvoted answer deleted once, and deleted again when reposted? 的主题
相关的 CORS 深入研究了同样的错误,但与来自 S3 / Cloudfront 的缓存和标头触发它也在这里:stackoverflow.com/questions/44800431/…

T
TylerH

如果我理解正确,您正在对与您的页面所在的域不同的域执行 XMLHttpRequest。因此浏览器会阻止它,因为出于安全原因,它通常允许同一来源的请求。当您想要进行跨域请求时,您需要做一些不同的事情。 Using CORS 是关于如何实现这一目标的教程。

当您使用 Postman 时,它们不受此政策的限制。引自Cross-Origin XMLHttpRequest

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


浏览器没有阻止请求。唯一完全阻止跨域 ajax 请求的浏览器是 IE7 或更早版本。所有浏览器,除了 IE7 和更早版本,都实现了 CORS 规范(部分 IE8 和 IE9)。您需要做的就是通过根据请求返回正确的标头来选择加入 API 服务器上的 CORS 请求。您应该在 mzl.la/VOFrSz 阅读 CORS 概念。 Postman 也通过 XHR 发送请求。如果您在使用邮递员时没有看到同样的问题,这意味着您在不知不觉中没有通过邮递员发送相同的请求。
@MD.SahibBinMahboob 邮递员没有“从您的 java/python”代码发送请求。它直接从浏览器发送请求。 XHR in Chrome extensions does work a bit differently, especially when cross-origin requests are involved
M
Machavity

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

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

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

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

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


您不应该关闭 CORS,因为您不知道它的用途。这使您的用户处于根本不安全的状态。
尽管它可能不安全,但问题不在于安全性,而在于如何完成任务。这是开发人员在处理跨域 AJAX 请求时必须选择的选项之一。它帮助我解决了这个问题,对于我的应用程序,我不在乎数据来自哪里。我在目标域上使用 PHP 清理所有输入,所以,如果有人想向它发布一些垃圾,让他们试试。这里的要点是,可以从目标域允许跨域 AJAX。 +1 的答案。
@meagar 同意您的观点,我们不应该关闭 CORS,但有时我们需要在开发应用程序时对其进行测试,为此,最简单的方法是关闭 CORS 并检查一切是否正常。很多时候,前端开发人员无法访问后端系统,他们无法在后端系统中进行更改,或者他们需要为此编写代理。添加用于开发目的的关闭 CORS 的 chrome 扩展的最佳方法,如已删除的答案中所写。
如果在 php.ini 中使用该 header() 脚本,如果答案(或顶部带有警告的编辑)向谁解释有风险,那应该会很有帮助。这里的问题是关于一个我们无法控制的外国站点,它只允许我们从浏览器导航和查看它,而如果我们需要从我们的服务器访问资源,它会启动 CORS 保护(不让我们每秒查询太多)。因此,我的问题仍然存在,如果在我们的服务器中使用 header() 脚本,我们的访问者会有什么危险?编辑是否将访客(我们)与主持人混淆了?
@Eve CORS 保护与每秒的查询数量无关!它拒绝任何其他网站使用您的资源服务或页面。该警告已经包含两个链接来解释什么是风险
C
Community

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

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

对于 C# 网络服务 - Web API

请在 标签下的 web.config 文件中添加以下代码。这将起作用:

<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");

K
Kamil Kiełczewski

深的

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

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

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

设置标头 Host=example.com (您的 API)

未设置标题来源

Postman 实际上根本不使用您的网站网址(您只需在 Postman 中输入您的 API 地址) - 他只向 API 发送请求,因此他假设网站与 API 具有相同的地址(浏览器不假设这一点)

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

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

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

设置标题 Host=example.com (你的作为 API)

设置标题 Origin=http://my-site.local:8088 (您的站点)

(标头 RefererOrigin 具有相同的值)。现在在 Chrome 的 Console &网络 标签,您将看到:

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

https://i.stack.imgur.com/8ITev.png

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

Origin=null 在您从本地目录打开 HTML 内容并发送请求时设置。同样的情况是当您在 <iframe> 中发送请求时,就像在下面的代码段中一样(但这里根本没有设置 Host 标头)- 通常,在 HTML 规范中提到不透明来源的任何地方,您都可以将其翻译到 Origin=null。有关这方面的更多信息,您可以找到 here

fetch('http://example.com/api', {method: 'POST'});查看 chrome-console > 网络选项卡

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

fetch('http://example.com/api', { method: 'POST', headers: { 'Content-Type': 'application/json'} });在 chrome-console -> 网络选项卡中查看“api”请求。这是 OPTIONS 请求(服务器不允许发送 POST 请求)

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

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

location ~ ^/index\.php(/|$) { ... add_header 'Access-Control-Allow-Origin' "$http_origin" 总是; add_header 'Access-Control-Allow-Credentials' 'true' 总是; if ($request_method = OPTIONS) { add_header 'Access-Control-Allow-Origin' "$http_origin"; # 不要删除此行(与上面的外部“if”加倍) add_header 'Access-Control-Allow-Credentials' 'true'; add_header '访问控制-最大年龄' 1728000; # 缓存 20 天的预检值 add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' '我的第一个标题,我的第二个标题,授权,内容类型,接受,来源'; add_header '内容长度' 0; add_header 'Content-Type' 'text/plain charset=UTF-8';返回204; } }

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

#------------------------------------------------ ----------------------------------------- # |跨域 Ajax 请求 | #------------------------------------------------ ----------------------------- # 启用跨域 Ajax 请求。 # http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity # http://enable-cors.org/ # # 标头设置 Access-Control-Allow-Origin "*" # # Header set Header set Access-Control-Allow-Origin "*" # Header 总是设置 Access-Control-Allow-Credentials "true" Access-Control-Allow-Origin "http://your-page.com :80" 标头始终设置 Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT" 标头始终设置 Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content -type, csrf-token"


很好很好的解释,很容易赶上!感谢你!
P
Peter Mortensen

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

浏览器查看服务器的 CORS 策略并尊重它。

但是,Postman 工具并不关心服务器的 CORS 策略。

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


J
JacquesB

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

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

Postman 没有实现 CORS 限制,这就是为什么在从 Postman 发出相同调用时看不到相同错误的原因。

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


@MrJedi:接受的答案没有解释为什么请求在邮递员中成功,这是最初的问题。
服务器最初的目的是向客户端(浏览器软件程序)发送流,而不是向各种桌面或服务器应用程序发送流,而是以扭曲的方式运行。浏览器与服务器建立握手协议,收到关于连接的确认,然后数据流恢复。在某些(DDOS)情况下,机器人场服务器发送了数百万个查询,并且主机向这些停滞的连接中的每一个提交了许多资源(打开的进程),这些连接最终从未发生过 - 从而阻止了其回答其他合法请求的能力
S
Stas Sorokin

解决方案和问题起源

您正在向不同的域创建 XMLHttpRequest,例如:

域一:some-domain.com 域二:some-different-domain.com

域名的这种差异触发了名为 SOP (Same-Origin Policy) 的 CORS (Cross-Origin Resource Sharing) 政策,该政策强制使用相同的域(因此 Origin) 在 Ajax、XMLHttpRequest 和其他 HTTP 请求中。

为什么当我通过 Chrome 扩展 Postman 发出请求时它会起作用?

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

大多数浏览器都会执行同源策略以防止与 CSRF (Cross-Site Request Forgery) 攻击相关的问题。

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


D
Daniel Iftimie

用于浏览器测试目的:Windows - 运行:

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

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

如果您的网关超时太短并且您正在访问的资源的处理时间比超时时间长,您也可能会收到此错误。这可能是复杂的数据库查询等的情况。因此,上面的错误代码可以掩盖这个问题。只需检查错误代码是否为 504 而不是 404,如上面的 Kamils 回答或其他内容。如果是 504,那么增加网关超时可能会解决问题。

在我的情况下,可以通过在 IE 浏览器中禁用同源策略 (CORS) 来消除 CORS 错误,请参阅 How to disable same origin policy Internet Explorer。执行此操作后,日志中出现纯 504 错误。


如果你得到超时,你不会得到 CORS 错误
好吧,我确实对系统进行了故障排除,但 CORS 错误让我失望了,只是超时太短,导致连接关闭。增加超时时间后,系统表现完美。所以是的,超时导致了 No 'Access-Control-Allow-Origin' 错误,这让我首先进入了这个线程。因此,这可能对其与 504 一起抛出的其他人有所帮助。
这意味着您的应用程序配置有问题。您不应该在超时时收到此错误
l
lunarzshine

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

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

代替 "*" 键入正在访问该网站的网站或 api url 端点。


B
Bapan Biswas

您的 IP 未列入白名单,因此您收到此错误。要求后端人员将您正在访问的服务的 IP 列入白名单 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers


L
Liban

“您可以做出的最快修复是安装 moesif CORS 扩展:https://chrome.google.com/webstore/detail/moesif-origin-cors-change/digfbfaphojjndkpccljibejjbppifbc/related?hl=en-US

安装后,在浏览器中单击它以激活扩展程序。确保图标的标签从“关闭”变为“打开”:

然后刷新您的应用程序,您的 API 请求现在应该可以工作了!”


这个可行,但这不是永久解决方案永久解决方案只能由后端完成