为啥我的 JavaScript 代码会收到“请求的资源上不存在 'Access-Control-Allow-Origin' 标头”错误,而 Postman 却没有?
Posted
技术标签:
【中文标题】为啥我的 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?为什么我的 JavaScript 代码会收到“请求的资源上不存在 'Access-Control-Allow-Origin' 标头”错误,而 Postman 却没有? 【发布时间】:2017-11-07 01:51:33 【问题描述】:Mod note:这个问题是关于为什么
XMLHttpRequest
/fetch
/etc。浏览器上的受相同访问策略限制(您收到提及 CORB 或 CORS 的错误),而 Postman 则不受此限制。这个问题不是关于如何修复“No 'Access-Control-Allow-Origin'...”错误。这是关于它们发生的原因。
请停止发帖:
适用于所有语言/框架的 CORS 配置。而是find your relevant language/framework's question。 允许请求绕过 CORS 的第三方服务 用于为各种浏览器关闭 CORS 的命令行选项
我正在尝试通过连接到RESTful API 内置Flask 来使用javascript 进行授权。但是,当我提出请求时,我收到以下错误:
XMLHttpRequest 无法加载 http://myApiUrl/login。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此不允许访问 Origin 'null'。
我知道API或远程资源必须设置header,但是为什么当我通过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? 的主题 【参考方案1】:用于浏览器测试目的: Windows - 运行:
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
【讨论】:
【参考方案2】:解决方案和问题来源
您正在向不同的域发送XMLHttpRequest,例如:
-
域一:
some-domain.com
域二:some-different-domain.com
域名的这种差异触发了名为 SOP (Same-Origin Policy) 的 CORS (Cross-Origin Resource Sharing) 策略,该策略强制使用相同的域(因此 Origin ) 在Ajax、XMLHttpRequest 和其他 HTTP 请求中。
为什么当我通过 Chrome 扩展程序发出请求时它起作用了 邮递员?
客户端(大多数浏览器和开发工具)可以选择执行同源策略。
大多数浏览器都会执行同源策略以防止与 CSRF (Cross-Site Request Forgery) 攻击相关的问题。
Postman作为开发工具选择不强制执行 SOP,而某些浏览器强制执行,这就是为什么您可以通过 Postman 发送请求,而您无法使用浏览器通过 JS 发送 XMLHttpRequest。
【讨论】:
【参考方案3】:如果您的网关超时太短并且您访问的资源的处理时间比超时时间长,您也可能会收到此错误。这可能是复杂的数据库查询等的情况。因此,上面的错误代码可以掩盖这个问题。只需检查错误代码是否为 504 而不是 404,如上面的 Kamils 答案或其他内容。如果是 504,那么增加网关超时可能会解决问题。
在我的情况下,可以通过在 IE 浏览器中禁用同源策略 (CORS) 来消除 CORS 错误,请参阅How to disable same origin policy Internet Explorer。执行此操作后,日志中出现纯 504 错误。
【讨论】:
如果你得到超时,你不会得到 CORS 错误 好吧,我在对系统进行故障排除时遇到了 CORS 错误,这让我大吃一惊,只是超时太短,导致连接关闭。增加超时时间后,系统表现完美。所以是的,超时导致了 No 'Access-Control-Allow-Origin' 错误,这让我首先进入了这个线程。因此,这可能对其与 504 一起抛出的其他人有所帮助。 这意味着您的应用程序配置有问题。您不应该在超时时收到此错误【参考方案4】:如果我理解正确,您正在对与您的页面所在的域不同的域执行XMLHttpRequest。因此浏览器会阻止它,因为出于安全原因,它通常允许同一来源的请求。当您想要进行跨域请求时,您需要做一些不同的事情。 Using CORS 是一个关于如何实现的教程。
当您使用 Postman 时,它们不受此政策的限制。引用自Cross-Origin XMLHttpRequest:
常规网页可以使用 XMLHttpRequest 对象从远程服务器发送和接收数据,但它们受到同源策略的限制。扩展并没有那么有限。只要首先请求跨域权限,扩展程序就可以与其源之外的远程服务器通信。
【讨论】:
浏览器没有阻塞请求。唯一完全阻止跨域 ajax 请求的浏览器是 IE7 或更早版本。所有浏览器,除了 IE7 和更早版本,都实现了 CORS 规范(部分 IE8 和 IE9)。您需要做的就是通过根据请求返回正确的标头来选择加入 API 服务器上的 CORS 请求。您应该在 mzl.la/VOFrSz 阅读 CORS 概念。 Postman 也通过 XHR 发送请求。如果您在使用 postman 时没有看到同样的问题,这意味着您在不知不觉中没有通过 postman 发送相同的请求。 @MD.SahibBinMahboob 邮递员没有“从您的 java/python”代码发送请求。它直接从浏览器发送请求。 XHR in Chrome extensions does work a bit differently, especially when cross-origin requests are involved.【参考方案5】:您得到的错误是由于 CORS 标准造成的,该标准对 JavaScript 如何执行 ajax 请求设置了一些限制。
CORS 标准是在浏览器中实现的客户端标准。因此,阻止调用完成并生成错误消息的是浏览器,而不是服务器。
Postman 没有实现 CORS 限制,这就是为什么在从 Postman 发出相同调用时看不到相同错误的原因。
为什么 Postman 不实施 CORS? CORS 定义了与发起请求的页面的来源(URL 域)相关的限制。但在 Postman 中,请求并非来自带有 URL 的页面,因此 CORS 不适用。
【讨论】:
@MrJedi:接受的答案没有解释为什么请求在 Postman 中成功,这是最初的问题。 服务器最初的目的是向客户端(浏览器软件程序)发送流,而不是向各种桌面或服务器应用程序发送流,而是以扭曲的方式运行。浏览器与服务器建立握手协议,收到关于连接的确认,然后数据流恢复。在某些 (DDOS) 情况下,机器人场服务器发送了数百万个查询,并且主机向这些停滞的连接中的每一个提交了许多资源(打开的进程),这些连接最终从未发生过 - 从而阻止了它回答其他合法请求的能力【参考方案6】:因为 $.ajax(type: "POST" - 调用 OPTIONS $.post( - 调用发布
两者是不同的。 Postman 正确调用“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");
【讨论】:
【参考方案7】:应用 CORS 限制是由服务器定义并由浏览器实现的安全功能。
浏览器查看服务器的 CORS 策略并遵守它。
但是,Postman 工具并不关心服务器的 CORS 策略。
这就是 CORS 错误出现在浏览器中的原因,而 Postman 中却没有。
【讨论】:
【参考方案8】:警告:使用
Access-Control-Allow-Origin: *
会使您的API/网站容易受到cross-site request forgery (CSRF) 攻击。在使用此代码之前,请确保您 understand the risks。
如果你使用php,解决起来非常简单。只需在处理请求的 PHP 页面的开头添加以下脚本:
<?php header('Access-Control-Allow-Origin: *'); ?>
如果您使用的是 Node-red,则必须通过取消注释以下行来允许 CORS 在 node-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 documentation。
【讨论】:
您不应该关闭 CORS,因为您不知道它的用途。这会使您的用户处于根本不安全的状态。 尽管它可能不安全,但问题不在于安全性,而在于如何完成任务。这是开发人员在处理跨域 AJAX 请求时必须选择的选项之一。它帮助我解决了这个问题,对于我的应用程序,我不在乎数据来自哪里。我在目标域上使用 PHP 清理所有输入,所以,如果有人想向它发布一些垃圾,让他们试试。这里的要点是,可以从目标域允许跨域 AJAX。为答案 +1。 @meagar 同意您的观点,我们不应该启用 CORS,但有时我们需要在开发应用程序时对其进行测试,为此,最简单的方法是启用 CORS 并检查是否一切正常美好的。很多时候,前端开发人员无法访问后端系统,他们无法在后端系统中进行更改,或者他们需要为此编写代理。添加用于开发目的的关闭 CORS 的 chrome 扩展的最佳方法,如已删除的答案中所述。 如果在 php.ini 中使用 header() 脚本,如果答案(或顶部带有 WARNING 的编辑)能够向谁解释有风险,那应该会很有帮助。这里的问题是关于一个我们无法控制的外部站点,它只允许我们从浏览器导航和查看它,而如果我们需要从我们的服务器访问资源,它会启动 CORS 保护(不让我们每秒查询太多)。因此,我的问题仍然存在,如果在我们的服务器中使用 header() 脚本,我们的访问者会有什么危险?编辑是否将访客(我们)与主持人混淆了? @Eve CORS 保护与每秒的查询数量无关!它拒绝任何其他网站使用您的资源服务或页面。该警告已经包含两个链接来解释什么是风险【参考方案9】:在以下作为 API 的调查中,我使用 http://example.com 而不是您问题中的 http://myApiUrl/login,因为这是第一个工作。
我假设您的页面位于http://my-site.local:8088.
你看到不同结果的原因是邮递员:
设置标题Host=example.com
(你的API)
未设置标题Origin
这类似于站点和 API 具有相同域时浏览器发送请求的方式(浏览器也设置了标题项Referer=http://my-site.local:8088
,但我在 Postman 中看不到)。 当Origin
标头未设置时,通常服务器默认允许此类请求。
这是 Postman 发送请求的标准方式。但是,当您的站点和 API 具有不同的域时,浏览器会发送不同的请求,然后出现 CORS 并且浏览器会自动:
设置标题Host=example.com
(你的作为API)
设置标题Origin=http://my-site.local:8088
(您的网站)
(标头Referer
与Origin
具有相同的值)。现在在 Chrome 的 Console & Networks 标签中,您将看到:
当你有 Host != Origin
时,这是 CORS,当服务器检测到这样的请求时,它通常默认阻止它。
Origin=null
在您从本地目录打开 HTML 内容并发送请求时设置。同样的情况是当您在<iframe>
中发送请求时,就像在下面的 sn-p 中一样(但这里根本没有设置 Host
标头)- 通常,在 HTML 规范中提到不透明来源的任何地方,您都可以将其翻译为Origin=null
。有关这方面的更多信息,您可以找到here。
fetch('http://example.com/api', method: 'POST');
Look on chrome-console > network tab
如果你不使用简单的 CORS 请求,通常浏览器在发送主请求之前也会自动发送一个 OPTIONS 请求 - 更多信息是here。下面的sn-p显示它:
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 请求。
这是一个示例配置,它打开 CORS on nginx(nginx.conf 文件) - 为 nginx 设置 always/"$http_origin"
和为 Apache 设置 "*"
时要非常小心 - 这将解除对 CORS 的阻止任何域。
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;
这是一个打开 CORS on Apache 的示例配置(.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"
【讨论】:
以上是关于为啥我的 JavaScript 代码会收到“请求的资源上不存在 'Access-Control-Allow-Origin' 标头”错误,而 Postman 却没有?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 JavaScript 代码会收到“请求的资源上不存在 'Access-Control-Allow-Origin' 标头”错误,而 Postman 却没有?
为啥我的 JavaScript 代码会收到“请求的资源上不存在 'Access-Control-Allow-Origin' 标头”错误,而 Postman 却没有?
为啥我的 JavaScript 代码会收到“请求的资源上不存在 'Access-Control-Allow-Origin' 标头”错误,而 Postman 却没有?
为啥我的 JavaScript 代码会收到“请求的资源上不存在 'Access-Control-Allow-Origin' 标头”错误,而 Postman 却没有?
为啥我的 JavaScript 代码会收到“请求的资源上不存在 'Access-Control-Allow-Origin' 标头”错误,而 Postman 却没有?
为啥我的 JavaScript 代码会收到“请求的资源上不存在 'Access-Control-Allow-Origin' 标头”错误,而 Postman 却没有?