为什么我的 JavaScript 代码没有 Postman 时出现 “在请求的资源上没有'Access-Control-Allow-Origin'标头” 错误?

我试图通过连接到Flask内置的RESTful API来使用JavaScript进行授权。但是,当我发出请求时,出现以下错误:

XMLHttpRequest 无法加载http:// myApiUrl / login 。所请求的资源上没有 “Access-Control-Allow-Origin” 标头。因此,不允许访问原始 “空”。

我知道 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);
    });

答案

如果我理解正确,那么您正在向页面所在的其他域执行XMLHttpRequest 。因此,由于安全原因,浏览器通常会阻止来自同一来源的请求,因此阻止了它。当您想进行跨域请求时,需要做一些不同的事情。有关如何实现此目标的教程是使用 CORS

使用邮递员时,它们不受此政策的限制。引用自跨域 XMLHttpRequest

常规网页可以使用 XMLHttpRequest 对象从远程服务器发送和接收数据,但是它们受同一原始策略的限制。扩展不受限制。扩展可以在其起源之外与远程服务器通信,只要它首先请求跨域许可。

这不是针对生产的解决方案,也不是必须将应用程序显示给客户端的解决方案,这仅在 UI 和后端开发位于不同服务器上且在生产中它们实际上位于同一服务器上时才有用。例如:在为任何应用程序开发 UI 时,如果需要在本地对其进行测试以将其指向后端服务器,那么在这种情况下,这是完美的解决方案。 对于生产修复,必须将 CORS 标头添加到后端服务器,以允许跨源访问。

简单的方法是只在 Google chrome 中添加扩展名,以允许使用 CORS 进行访问。

https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?hl=zh-CN

只要您想允许不访问任何“access-control-allow-origin”头请求,就启用此扩展。

要么

在 Windows 中,将此命令粘贴到运行窗口中

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

这将打开一个新的Chrome浏览器,该浏览器不允许访问“access-control-allow-origin”标头请求。

如果可以处理JSON ,请尝试使用JSONP (请注意末尾的P )在域之间进行发言:

$.ajax({
  type: "POST",
  dataType: 'jsonp',
  ...... etc ......

在此处了解有关使用 JSONP 的更多信息:

JSONP 的出现(本质上是一种共识性的跨站点脚本黑客)为强大的内容混搭打开了大门。许多著名的站点都提供 JSONP 服务,使您可以通过预定义的 API 访问其内容。

警告:在生产环境中使用此答案可能会导致安全问题,任何具有 URL(包括攻击者)的人都可以调用您的 API / 服务。您必须使用会话和 Cookie 进行身份验证,以防止您的 API / 服务受到此攻击。您的 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

然后在您的应用程序中包含烧瓶

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!"

有关更多详细信息,您可以查看烧瓶文档

我希望有人在很早以前就与我共享了此站点http://cors.io/ ,与构建和依赖我自己的代理相比,它将节省大量时间。但是,在进入生产阶段时,拥有自己的代理服务器是最好的选择,因为您仍然可以控制数据的各个方面。

一切你需要的:

https://cors.io/?http://HTTP_YOUR_LINK_HERE

如果您使用的是Node.js ,请尝试:

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

详细信息: ExpressJS 上的 CORS

使用 Ajax 存在跨域问题。您必须确定要在没有www.的同一http://路径上访问文件www. (或从http://www.访问并发布到包含www.的相同路径),当通过www.访问时浏览器将其视为另一个域www.路径,以便您查看问题出在哪里。您正在发布到另一个域,并且由于起源问题,浏览器阻止了流量。

如果API不在您请求的同一主机上,则该流程将被阻止,您将需要寻找另一种与 API 进行通信的方式。

因为
$ .ajax({type:“ POST” - 调用OPTIONS
$ .post( - 呼叫POST

两者都是不同的邮递员正确地称呼 “POST”,但是当我们称呼它为 “OPTIONS” 时

对于 C#Web 服务 - WebAPI

请在 标记下的 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");
    }
});

Angular 4 问题请参考: http : //www.hubfly.com/blog/solutions/how-to-fix-angular-4-api-call-issues/

注意:如果您要从第三方网站下载内容那么这将无济于事 。您可以尝试以下代码,但不能尝试 JavaScript。

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

试试XDomain

简介:纯 JavaScript CORS 替代 / polyfill。无需服务器配置 - 只需在要与之通信的域上添加 proxy.html。该库使用 XHook 挂钩所有XHR ,因此 XDomain 应该与任何库一起使用。

如果您不想:

  1. 在 Chrome 中禁用网络安全
  2. 使用 JSONP
  3. 使用第三方网站重新路由您的请求

并且您确定服务器随后启用了 CORS(在此处测试 CORS: http//www.test-cors.org/

然后,您需要在请求中传递 origin 参数。该来源必须与您的浏览器发送的与您的请求匹配的来源。

您可以在这里查看其运行情况: http : //www.wikinomad.com/app/detail/Campgrounds/3591

编辑功能将 GET&POST 请求发送到另一个域以获取数据。我设置了可以解决问题的 origin 参数。后端是 mediaWiki 引擎。

tldr:在您的调用中添加 “origin” 参数,该参数必须是浏览器发送的 Origin 参数(您不能欺骗 origin 参数)