添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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

2024-11-02 20:48:00
admin
摘要 :问题描述:Mod 注:这个问题是关于为什么浏览器上的XMLHttpRequest/ fetch/etc. 受到相同的访问策略限制(您会收到提及 CORB 或 CORS 的错误),而 Postman 却不受限制。这个问题不是关于如何修复“无‘Access-Control-Allow-Origin’...”错误。...

问题描述:

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> 标签下添加以下代码。这将起作用:

&lt;httpProtocol>
    &lt;customHeaders>
        &lt;add name=&quot;Access-Control-Allow-Origin&quot; value=&quot;*&quot; />
    &lt;/customHeaders>
&lt;/httpProtocol>

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

jQuery

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

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

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString(&quot;http://mysite.microsoft.sample.xyz.com/api/mycall&quot;);

解决方案 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 内容时,会设置该请求,并发送请求。当您在 内发送请求时 &lt;iframe> ,情况也一样,如下面的代码片段所示(但此处 Host 根本没有设置标头) - 通常,HTML 规范中提到不透明来源的地方,您都可以将其转换为。您可以在此处 Origin=null 找到有关此内容的更多信息。

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

运行代码片段Hide results展开片段

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

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

运行代码片段Hide results展开片段

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

下面是在 nginx 上 启用 CORS 的示例配置(nginx.conf 文件) - 在设置 always/&quot;$http_origin&quot; nginx 和Apache 时要非常小心 &quot;*&quot; - 这将解除对任何域的 CORS 阻止(在生产中,使用消耗 api 的具体页面地址而不是星号)

显示代码片段

location ~ ^/index.php(/|$) {
    add_header &#039;Access-Control-Allow-Origin&#039; &quot;$http_origin&quot; always;
    add_header &#039;Access-Control-Allow-Credentials&#039; &#039;true&#039; always;
    if ($request_method = OPTIONS) {
        add_header &#039;Access-Control-Allow-Origin&#039; &quot;$http_origin&quot;; # DO NOT remove THIS LINES (doubled with outside &#039;if&#039; above)
        add_header &#039;Access-Control-Allow-Credentials&#039; &#039;true&#039;;
        add_header &#039;Access-Control-Max-Age&#039; 1728000; # cache preflight value for 20 days
        add_header &#039;Access-Control-Allow-Methods&#039; &#039;GET, POST, OPTIONS&#039;;
        add_header &#039;Access-Control-Allow-Headers&#039; &#039;My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin&#039;;
        add_header &#039;Content-Length&#039; 0;
        add_header &#039;Content-Type&#039; &#039;text/plain charset=UTF-8&#039;;
        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/
# &lt;IfModule mod_headers.c>
#    Header set Access-Control-Allow-Origin &quot;*&quot;
# &lt;/IfModule>
# Header set Header set Access-Control-Allow-Origin &quot;*&quot;
# Header always set Access-Control-Allow-Credentials &quot;true&quot;
Access-Control-Allow-Origin &quot;http://your-page.com:80&quot;
Header always set Access-Control-Allow-Methods &quot;POST, GET, OPTIONS, DELETE, PUT&quot;
Header always set Access-Control-Allow-Headers &quot;My-First-Header,My-Second-Header,Authorization, content-type, csrf-token&quot;

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,例如:

  1. 域一: some-domain.com

  2. 领域二: 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=&quot;C://Chrome dev session&quot; --disable-web-security

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

解决方案 9:

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

在我的情况下,可以通过在Internet Explorer浏览器中禁用同源策略 (CORS) 来消除 CORS 错误,请参阅 如何禁用同源策略 Internet Explorer 。执行此操作后,日志中只有一个纯 504 错误。

解决方案 10:

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

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

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

解决方案 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

&lt;system.webServer>
     &lt;httpProtocol>
         &lt;customHeaders>
            &lt;add name=&quot;Access-Control-Allow-Origin&quot; value=&quot;*&quot; />
            &lt;add name=&quot;Access-Control-Allow-Methods&quot; value=&quot;*&quot; />
            &lt;add name=&quot;Access-Control-Allow-Headers&quot; value=&quot;*&quot; />
         &lt;/customHeaders>
     &lt;/httpProtocol>
&lt;/system.webServer>

解决方案 14:

对我来说,我只需更换浏览器,它就可以正常工作。我当时在 localhost 上工作。我的 API 在 localhost:7133 上,我的应用程序在 localhost:5173 上。在 Chrome 和 Edge 中,它不起作用,但当我尝试使用 Opera 时,它起作用了。我认为当我在不同的域上发布 API 和 Web 应用程序时,这将是一个解决方案。

解决方案 15:

我们的问题是 ModSecurity 在 nginx 上触发的。请求从未到达 PHP 服务器,并向 Google Chrome 返回 403;由于我们有两个不同的域(原域和目标域),因此 Chrome 认为缺少 CORS Access-Control-Allow-Origin 是 CORS 问题。

解决方案是将请求编码为 base64 或更新 nginx 上的 ModSecurity 设置以不再阻止该请求。

解决方案 16:

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

....
const cors = require(&quot;cors&quot;);
.....
app.use(cors());

解决方案 17:

它通过在全球范围内应用这个中间件来为我工作:

&lt;?php
    namespace AppHttpMiddleware;
    use Closure;
    class Cors {
       public function handle($request, Closure $next) {
           return $next($request)
                   ->header(&#039;Access-Control-Allow-Origin&#039;, &#039;*&#039;)
                   ->header(&#039;Access-Control-Allow-Methods&#039;, &#039;GET, POST, PUT, DELETE, OPTIONS&#039;)
                   ->header(&#039;Access-Control-Allow-Headers&#039;, &quot;Accept,authorization,Authorization, Content-Type&quot;);
	为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...        
                          项目管理软件
	在项目管理领域,集成产品开发(IPD)流程被视为提升产品创新与市场竞争力的关键方法。然而,实践过程中,不少企业因对IPD理解不深或执行不当,而陷入了一系列常见误区。本文旨在剖析这些误区,并提出相应的规避策略,以期帮助企业更有效地运用IPD流程,加速产品上市,提升市场成功率。误区一:IPD流程僵化,缺乏灵活性IPD流程强...        
                          华为IPD流程
	PDCP在IPD中的角色:8个关键要点在集成产品开发(IPD)流程中,PDCP(Plan Decision Check Point,计划决策评审点)扮演着至关重要的角色。作为产品开发过程中的一个重要里程碑,PDCP不仅决定了项目是否进入下一阶段,还确保了产品设计和关键流程的合理性、可行性和合规性。本文将深入探讨PDCP...        
                          IPD结构化流程
	在当今快速变化的商业环境中,企业为了保持竞争力,必须不断推出创新产品以满足市场需求。集成产品开发(IPD, Integrated Product Development)流程作为一种先进的研发管理模式,旨在通过跨部门协作、高效决策和快速迭代,加速产品从概念到市场的转化过程。成功实施IPD流程并非一蹴而就,它需要企业系统...        
                          华为IPD流程
	PDCP在IPD中的实施挑战与解决方案在集成产品开发(IPD)流程中,计划决策评审(PDCP)作为关键节点,对确保产品设计和关键流程的合理性、可行性及符合性起着至关重要的作用。然而,PDCP的实施并非一帆风顺,它面临着多方面的挑战。本文将深入探讨这些挑战,并提出相应的解决方案,以期为项目管理实践提供有价值的参考。一、P...        
                          华为IPD流程