题 为什么我的JavaScript在所请求的资源上出现“No'Access-Control-Allow-Origin'标头”错误,当Postman没有?


我正在尝试使用授权 JavaScript的 通过连接到 REST风格  API 内置的 烧瓶。但是,当我发出请求时,我收到以下错误:

XMLHttpRequest无法加载 HTTP:// myApiUrl /登录。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此不允许原点'null'访问。

我知道API或远程资源必须设置标头,但为什么在我通过Chrome扩展程序发出请求时它才有效 邮差

这是请求代码:

$.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);
    });

1869
2017-11-17 19:29


起源


您是从localhost执行请求还是直接执行HTML? - MD. Sahib Bin Mahboob
@ MD.SahibBinMahboob如果我理解你的问题我从localhost请求 - 我的计算机上有页面并运行它。当我在托管上部署网站时,它给出了相同的结果。 - Mr Jedi
您执行的页面的域名和请求的域名是相同还是不同? - MD. Sahib Bin Mahboob
很多相关: stackoverflow.com/questions/10143093/... - cregox
对于寻求更多阅读的人来说,MDN有一篇关于ajax和跨域请求的好文章: developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS - Sam Eaton


答案:


如果我理解得对,你就是在做 XMLHttpRequest的 到您的网页所在的不同域。因此浏览器阻止它,因为出于安全原因,它通常允许同一来源的请求。当您想要执行跨域请求时,您需要执行不同的操作。关于如何实现这一目标的教程是 使用CORS

当您使用邮递员时,他们不受此政策的限制。引自 跨源XMLHttpRequest

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


1008
2017-11-17 19:49



你是对的。我对不同的域请求比我的页面请求。 API在服务器上,我从localhost运行请求。在我接受回答之前你能解释一下“直接执行请求”是什么意思吗? POSTMAN不使用域名? - Mr Jedi
浏览器未阻止请求。唯一直接阻止跨源ajax请求的浏览器是IE7或更早版本。除IE7及更早版本之外的所有浏览器都实现了CORS规范(部分是IE8和IE9)。您需要做的就是通过根据请求返回正确的标头来选择加入API服务器上的CORS请求。您应该阅读CORS概念 mzl.la/VOFrSz。邮递员也通过XHR发送请求。如果您在使用邮递员时没有看到同样的问题,这意味着您在不知不觉中没有通过邮递员发送相同的请求。 - Ray Nicholus
@ MD.SahibBinMahboob Postman没有“从你的java / python”代码发送请求。它直接从浏览器发送请求。 Chrome扩展程序中的XHR确实有所不同,特别是涉及跨源请求时。 - Ray Nicholus
@yves它是实际施加规则的浏览器。因此,从任何地方而不是浏览器发起请求应该是工作文件 - MD. Sahib Bin Mahboob
@SuhailGupta,如果你允许服务器中的起源,它将被允许执行实际上称为CORS的请求。 - MD. Sahib Bin Mahboob


这不是生产修复或必须向客户端显示应用程序时,这仅在UI和后端时有用 发展  是不同的 服务器 在生产中,它们实际上在同一台服务器上。例如:在为任何应用程序开发UI时,如果需要在本地测试它指向后端服务器,在这种情况下,这是一个完美的修复。 对于生产修复,必须将CORS头添加到后端服务器以允许跨源访问。

简单的方法是在谷歌浏览器中添加扩展名以允许使用CORS进行访问。

https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en-US

只要您希望允许访问no,只需启用此扩展 “访问控制允许来源” 标头请求。

要么 

在Windows中,粘贴此命令  窗口

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

这将开启一个新的  浏览器允许访问否 “访问控制允许来源” 标头请求。


450
2018-03-04 06:42



这很棒,但不能要求客户以这种方式启动chrome来强制执行webservice调用的内部要求。 - Taersious
这不应该被接受作为答案,安装第三方插件来修复你的应用程序,而不是理解CORS和修复你的应用程序,其他人将如何使用你的api?你会让他们全部安装这个插件 - James Kirkby
我安装了这个扩展并做了一个请求,而不是在fiddler中检查了请求,指定了以下内容 - > Origin: evil.com 。看起来这个扩展正在改变Origin evil.com - wagwanJahMan
这个扩展就像一个魅力。但他们真的在内部做什么?有没有办法以Javascript或Jquery的方式做同样的事情,而不是使用插件? - sms
我认为这是一个非常好的答案 如果您不需要永久修复或者您只需要临时禁用CORS。 这就是我所需要的,这个解决方案非常有用。显然,这永远不会被视为永久解决方案。 - jtcotton63


如果你能处理 JSON 作为回报,然后尝试使用 JSONP (注意 P 最后)在域名之间发言:

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

了解有关使用JSONP的更多信息 这里

JSONP的出现 - 本质上是一个双方同意的跨站点脚本黑客 - 为强大的内容混搭打开了大门。许多着名网站都提供JSONP服务,允许您通过预定义的API访问其内容。


312
2018-02-22 00:42



请注意,jsonp不适用于POST内容。更多讨论 这里。 - Prabu Raja
当你不能将jsonp与POST请求一起使用时,如何获得如此多的票数?!?! - fatlog
当你使用 JSONP,$ .ajax将忽略 type,所以它总是如此 GET 这意味着这个答案永远有效。 - noob
看起来超过200人只是没有得到它 - cs01
另请注意,JSONP不能与JSON直接互换。你需要的 服务器 以JSONP格式返回数据。简单地改变了 dataType 仅在AJAX请求设置中是行不通的。 - Rory McCrossan


如果您正在使用它,解决起来非常简单 PHP。只需在处理请求的PHP页面的开头添加以下脚本:

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

警告: 这包含您的PHP文件的安全问题,攻击者可以调用它。您必须使用会话和cookie进行身份验证,以防止您的文件/服务遭受此攻击。您的服务容易受到攻击 跨站请求伪造 (CSRF)。

如果你正在使用 节点红 你必须允许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"
},

185
2017-12-03 20:24



问题根本不在于PHP。 - mknaf
而且它不安全 - llazzaro
你不应该 关掉 CORS因为你不知道它的用途。这是一个可怕的答案。 - meagar♦
即使它可能不安全,但问题不在于安全性,而在于如何完成任务。这是开发人员在处理跨域AJAX请求时必须选择的选项之一。它帮助我解决了这个问题,对于我的应用程序,我并不关心数据的来源。我在目标域上使用PHP清理所有输入,因此,如果有人想要发布一些垃圾,请让他们尝试。这里的要点是,可以从目标域允许跨域AJAX。答案为+1。 - ZurabWeb
虽然我同意皮耶罗给出的一般信息,但它并不是专门针对安全问题,而是安全问题。我认为这至少应该说“这通常很糟糕!除非你知道你在做什么,否则不要这样做!这里有更多关于它的文档:......”,也许可以简单地解释一下原因。我讨厌有人来这里,只想“哦,我可以添加/调整这个标题,我很好!”并不知道完整的后果。我的意思是,这对他们来说是研究和所有,但仍然。 - Thomas F.


我希望很久以前有人和我分享这个网站 http://cors.io/ 与构建和依赖我自己的代理相比,它可以节省大量时间。但是,当您转向生产时,拥有自己的代理是最好的选择,因为您仍然可以控制数据的所有方面。

一切你需要的:

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


143
2017-07-21 22:08



这有什么缺点?这些家伙是否在拦截我的数据? - Sebastialonso
cors.io/?u=HTTP_YOUR_LINK_HERE     (小修正) - jkpd
我不认为通过第三方代理发送您的数据是个好主意 - Daniel Alexandrov
一个缺点是它们有时会超载,就像它们现在一样。 This application is temporarily over its serving quota. Please try again later. - Daniel Hickman
也试试 https://crossorigin.me/http://example.com - KingRider


使用Ajax存在跨域问题。您必须确保您正在访问您的文件 http:// 没有路径 www. (或访问 http://www. 并发布到相同的路径,包括 www.)浏览器在通过a访问时认为是另一个域 www. 路径,所以你看到问题所在。您正在发布到其他域,并且浏览器会因原始问题阻止流。

如果 API 没有放在您请求的同一主机上,流被阻止,您将需要找到另一种与API通信的方式。


61
2018-03-12 08:53



是的,我被迫在我的phonegap应用程序中使用var app_url = location.protocol +'//'+ location.host +'/ api /。问题是有www的网站。前置会带来这个错误。 - Sir Lojik


如果你正在使用 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


55
2018-02-12 16:27



我正在给你投票,因为这正是我所需要的。但是认为推广“*”示例是一个坏主意,但没有解释它将允许任何连接,不应该在生产中使用。这在MDN链接中解释 developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS。 - rob
@rob感谢您的评论。你是对的,我们应该指定允许哪些来源使用资源。但是,如果资源用于公共目的,我们不了解消费者,我认为如果我没有错,我们应该使用“*”。 - Nguyen Tran
我已经使用了这个概念,我的问题在nodejs中解决了。谢谢 - Deepak Bhatta
app.use(function(req,res,next){res.setHeader('Access-Control-Allow-Origin','*'); res.setHeader('Access-Control-Allow-Methods','GET,POST ,OPTIONS,PUT,PATCH,DELETE'); res.setHeader('Access-Control-Allow-Headers','X-Requested-With,content-type,Authorization'); res.setHeader('Access-Control-Allow -Credentials',true); if('OPTIONS'=== req.method){res.send(204);} else {next();}}); - Ricky sharma
关于使用的危险 "Access-Control-Allow-Origin", "*",见 security.stackexchange.com/a/45677。 tldr: W3规范实际上建议:可以公开访问的资源,没有访问控制检查,可以始终安全地返回值为“*”的Access-Control-Allow-Origin标头 - CODE-REaD


因为
$ .ajax({type:“POST”   - 电话 OPTIONS 
$。员额(  - 电话 POST 

两者都是不同的Postman称之为“POST”,但当我们称之为“OPTIONS”时

对于c#web服务 - webapi 

请在<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");
    }
});

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");

41
2017-12-13 13:02



此配置在Azure服务上解决了Wordpress上的相同错误。谢谢。 - Andre Mesquita
我建议使用特定的原始值来避免来自外部域的请求。所以例如而不是 * 使用 https://www.myotherdomain.com - pechar


尝试 XDomain

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


22
2018-04-01 07:46





如果你不想:

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

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

然后你需要在你的请求中传入origin参数。 此来源必须与您的浏览器与您的请求一起发送的来源相匹配。

你可以在这里看到它: http://www.wikibackpacker.com/app/detail/Campgrounds/3591

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

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


9
2017-07-07 04:26



您是否引用此示例代码 main.min.js? t.post("https://wiki.wikinomad.com/api.php?origin=https://www.wikinomad.com", n, o).then(function(e) {...。如果是这样,这种指定原点的方式是否真的要求从“后端”提供的PHP被编码为支持它,否则这个答案将不起作用? - CODE-REaD