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

IT技术 javascript jquery cors same-origin-policy flask-restless
2021-01-03 21:37:20

Mod注:这个问题是关于为什么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);
    });
6个回答

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

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

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

@MD.SahibBinMahboob 邮递员不会“从您的 java/python”代码发送请求。它直接从浏览器发送请求。 Chrome 扩展中的 XHR 的工作方式略有不同,尤其是在涉及跨域请求时
2021-02-25 21:37:20
浏览器没有阻止请求。唯一完全阻止跨域 ajax 请求的浏览器是 IE7 或更早版本。除 IE7 及更早版本之外的所有浏览器都实现了 CORS 规范(部分 IE8 和 IE9)。您需要做的就是通过根据请求返回正确的标头来选择加入 API 服务器上的 CORS 请求。您应该在mzl.la/VOFrSz上阅读 CORS 概念Postman 也通过 XHR 发送请求。如果您在使用邮递员时没有看到同样的问题,这意味着您在不知不觉中没有通过邮递员发送相同的请求。
2021-03-05 21:37:20

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

如果您使用的是PHP则很容易解决只需在处理请求的 PHP 页面的开头添加以下脚本:

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

如果您正在使用节点红色的,你必须让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 文档

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

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

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

对于 C# Web 服务 - Web API

在 <system.webServer> 标签下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");

在下面作为 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 中没有看到)。没有设置Originheader 时,通常服务器默认允许这样的请求。

在此处输入图片说明

这是 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

如果您不使用简单的 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 - 在设置always/"$http_origin"nginx 和"*"Apache 时要非常小心- 这将解除对任何域的 CORS 的阻止。

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

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

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

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

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