为什么我的 JavaScript 代码会收到“请求的资源上不存在‘Access-Control-Allow-Origin’标头”错误,而 Postman 却不会?
- 2024-11-02 20:48:00
- admin 原创
- 62
问题描述:
Mod 注:这个问题是关于为什么浏览器上的
XMLHttpRequest
/fetch
/etc. 受到相同的访问策略限制(您会收到提及 CORB 或 CORS 的错误),而 Postman 却不受限制。这个问题不是关于如何修复“无‘Access-Control-Allow-Origin’...”错误。而是关于为什么会发生这种情况。
请停止发帖:
世界上所有语言/框架的 CORS 配置。请查找相关语言/框架的问题。
允许请求规避 CORS 的第三方服务
用于关闭各种浏览器的 CORS 的命令行选项
我正在尝试通过连接到Flask内置的RESTfulAPI使用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);
});
解决方案 1:
如果我理解正确的话,你正在向与页面所在域不同的域执行XMLHttpRequest。因此浏览器会阻止它,因为出于安全原因,它通常允许来自同一来源的请求。当您想要执行跨域请求时,您需要做一些不同的事情。
当你使用 Postman 时,它们不受此策略的限制。引自Cross-Origin XMLHttpRequest:
常规网页可以使用 XMLHttpRequest 对象从远程服务器发送和接收数据,但它们受到同源策略的限制。扩展程序不受此限制。扩展程序可以与其来源之外的远程服务器通信,只要它首先请求跨源权限即可。
解决方案 2:
警告:使用
Access-Control-Allow-Origin: *
可能会使您的 API/网站容易受到跨站点请求伪造(CSRF) 攻击。在使用此代码之前,请确保您了解相关风险。
如果您使用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 文档。
解决方案 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");
解决方案 4:
深的
在下面的 API 调查中,我使用http://example.com而不是问题中的 http://myApiUrl/login,因为这是第一个有效的。我假设您的页面位于http://my-site.local:8088。
注意:API 和您的页面有不同的域!
您看到不同结果的原因是 Postman:
设置标题
Host=example.com
(你的 API)未设置标题
Origin
Postman 实际上根本不使用您的网站网址(您只需在 Postman 中输入您的 API 地址) - 他只向 API 发送请求,因此他假设网站具有与 API 相同的地址(浏览器不假设这一点)
这类似于浏览器在站点和 API 具有相同域时发送请求的方式(浏览器也设置了 header item Referer=http://my-site.local:8088
,但我在 Postman 中没有看到它)。当未Origin
设置header时,通常服务器默认允许此类请求。
这是 Postman 发送请求的标准方式。但是,当你的站点和 API 有不同的域时,浏览器会以不同的方式发送请求,然后会发生CORS,并且浏览器会自动:
设置标题
Host=example.com
(你的 API)设置标题
Origin=http://my-site.local:8088
(您的网站)
(标头Referer
具有与 相同的值Origin
)。现在,在 Chrome 的“控制台和网络”选项卡中,您将看到:
当你有Host != Origin
这个是 CORS 时,当服务器检测到这样的请求时,它通常会默认阻止它。
Origin=null
当您从本地目录打开 HTML 内容时,会设置该请求,并发送请求。当您在 内发送请求时<iframe>
,情况也一样,如下面的代码片段所示(但此处Host
根本没有设置标头) - 通常,HTML 规范中提到不透明来源的地方,您都可以将其转换为。您可以在此处Origin=null
找到有关此内容的更多信息。
fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab
运行代码片段Hide results展开片段
如果你不使用简单的 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)
运行代码片段Hide results展开片段
您可以更改服务器的配置以允许 CORS 请求。
下面是在 nginx 上启用 CORS 的示例配置(nginx.conf 文件) - 在设置always/"$http_origin"
nginx 和Apache 时要非常小心"*"
- 这将解除对任何域的 CORS 阻止(在生产中,使用消耗 api 的具体页面地址而不是星号)
显示代码片段
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;
}
}
Run code snippetHide resultsExpand snippet
以下是在 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"
Run code snippetHide resultsExpand snippet
解决方案 5:
应用 CORS 限制是由服务器定义并由浏览器实现的安全功能。
浏览器查看服务器的 CORS 策略并尊重它。
但是Postman工具并不关心服务器的CORS策略。
这就是为什么CORS错误出现在浏览器中,但在Postman中没有出现的原因。
解决方案 6:
您收到的错误是由于 CORS 标准造成的,该标准对 JavaScript 如何执行 ajax 请求设置了一些限制。
CORS 标准是客户端标准,在浏览器中实现。因此,阻止调用完成并生成错误消息的是浏览器,而不是服务器。
Postman 没有实现 CORS 限制,这就是为什么从 Postman 进行相同调用时不会看到相同错误的原因。
为什么Postman 不实现 CORS?CORS 定义了相对于发起请求的页面来源(URL 域)的限制。但在 Postman 中,请求并非源自具有 URL 的页面,因此 CORS 不适用。
解决方案 7:
解决方案和问题起源
您正在向不同的域发出XMLHttpRequest,例如:
域一:
some-domain.com
领域二:
some-different-domain.com
这种域名差异会触发CORS(跨域资源共享)策略,即同源策略(SOP ),该策略强制在Ajax、XMLHttpRequest 和其他 HTTP 请求中使用相同的域(因此称为Origin) 。
为什么我通过 Chrome 扩展程序 Postman 发出请求时它会起作用?
客户端(大多数浏览器和开发工具)可以选择强制执行同源策略。
大多数浏览器都强制执行同源策略,以防止与CSRF(跨站点请求伪造)攻击相关的问题。
Postman作为开发工具选择不强制执行 SOP,而某些浏览器会强制执行,这就是为什么您可以通过 Postman 发送请求,而无法使用浏览器通过 JS 使用 XMLHttpRequest 发送请求的原因。
解决方案 8:
对于浏览器测试目的:
Windows——运行:
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
上述命令将禁用 chrome web 安全。因此,例如,如果您在本地项目上工作并在尝试发出请求时遇到 CORS 策略问题,则可以使用上述命令跳过此类错误。基本上,它将打开一个新的 chrome 会话。
解决方案 9:
如果您的网关超时时间太短,并且您访问的资源的处理时间比超时时间长,您也可能会收到此错误。对于复杂的数据库查询等,可能就是这种情况。因此,上述错误代码可能会掩盖此问题。只需检查错误代码是否为 504,而不是Kamil 的答案中的 404或其他内容。如果是 504,那么增加网关超时时间可能会解决问题。
在我的情况下,可以通过在Internet Explorer浏览器中禁用同源策略 (CORS) 来消除 CORS 错误,请参阅如何禁用同源策略 Internet Explorer。执行此操作后,日志中只有一个纯 504 错误。
解决方案 10:
要解决此问题,请在后端使用的doGet()
或函数中写入此行代码doPost()
response.setHeader("Access-Control-Allow-Origin", "*");
您可以输入访问该网站的网站或 API URL 端点,否则"*"
它将是公开的。
解决方案 11:
您的 IP 地址未列入白名单,因此出现此错误。请让后端工作人员将您的 IP 地址列入白名单,以供您访问服务。
访问控制允许标头
解决方案 12:
对我来说,我因为不同的原因遇到此问题,远程域被添加到原点,部署的应用程序运行完美,除了一个端点我遇到了这个问题:
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 数据库表后一切正常。
解决方案 13:
您可以通过在服务器的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>
解决方案 14:
对我来说,我只需更换浏览器,它就可以正常工作。我当时在 localhost 上工作。我的 API 在 localhost:7133 上,我的应用程序在 localhost:5173 上。在 Chrome 和 Edge 中,它不起作用,但当我尝试使用 Opera 时,它起作用了。我认为当我在不同的域上发布 API 和 Web 应用程序时,这将是一个解决方案。
解决方案 15:
我们的问题是ModSecurity
在 nginx 上触发的。请求从未到达 PHP 服务器,并向 Google Chrome 返回 403;由于我们有两个不同的域(原域和目标域),因此 Chrome 认为缺少 CORSAccess-Control-Allow-Origin
是 CORS 问题。
解决方案是将请求编码为 base64 或更新 nginx 上的 ModSecurity 设置以不再阻止该请求。
解决方案 16:
如果你使用 Node.js(Express.js)构建后端,请尝试使用npm i cors
....
const cors = require("cors");
.....
app.use(cors());
...
解决方案 17:
它通过在全球范围内应用这个中间件来为我工作:
<?php
namespace AppHttpMiddleware;
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");
}
}
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件