为什么我的JavaScript得到一个“否”访问控制 – 允许来源“标题出现在请求的资源”错误时,邮差不?

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

XMLHttpRequest无法加载http:// myApiUrl / login 。 请求的资源上没有“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); }); 

如果我理解正确,你正在做一个XMLHttpRequest到一个不同于你的页面的域。 所以浏览器会阻止它,因为出于安全原因,它通常允许同一个来源的请求。 当你想做一个跨域请求时,你需要做一些不同的事情。 关于如何实现这个教程是使用CORS

当你使用邮递员时,他们不受这个政策的限制。 引用来自跨源XMLHttpRequest

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

这不是修复生产或当应用程序必须显示给客户端时,这只有当UI和后端开发在不同的服务器上,并在生产中,他们实际上在同一台服务器上时才有用。 例如:在为任何应用程序开发UI时,如果需要对其进行本地testing,并将其指向后端服务器,则在这种情况下,这是完美的解决scheme。 对于生产修复,必须将CORS头添加到后端服务器以允许跨源访问。

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

https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?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访问其内容。

如果您使用PHP ,解决这个问题非常简单。 只需在处理请求的PHP页面的开始处添加以下脚本即可:

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

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

如果您使用Node-red ,则必须通过取消注释以下行来允许node-red/settings.js文件中的CROS:

 // 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" }, 

我希望有人与我分享这个网站很久以前http://cors.io/相比build立和依靠我自己的代理它会节省大量的时间。; 然而,随着您转向生产,拥有自己的代理是最好的select,因为您仍然控制着数据的各个方面。

一切你需要的:

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

有一个使用Ajax的跨域问题。 您必须确保您在没有www.的同一个http://path上访问您的文件www. (或者访问http://www.和post到包含www.的相同path),浏览器在通过www.访问时认为是另一个域www. path,所以你看到问题在哪里。 您正在发布到不同的域,并且由于原始问题,浏览器会阻止该stream。

如果API没有放置在您请求的同一主机上,则stream程被阻止,您将需要find另一种与API通信的方式。

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

对于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问题,请参阅如何解决Angular 4 API调用问题

尝试XDomain ,

简介:一个纯粹的JavaScript CORS替代/填充。 不需要服务器configuration – 只需在您希望与之通信的域上添加一个proxy.html即可。 这个库使用XHook钩住所有的XHR ,所以XDomain应该和任何库一起工作。

如果你不

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

你确定你的服务器启用了CORS,然后(在这里testingCORS: http : //test-cors.org/ )

那么你需要传递你的请求的原始参数。 该来源必须与您的浏览器发送的来源与您的请求相匹配。

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

编辑function将GET&POST请求发送到不同的域以获取数据。 我设置了解决问题的原始参数。 后端是一个mediaWiki引擎。

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

当我使用AngularJS来访问我的API时,我遇到了一个问题。 在SoapUI 5.0和ColdFusion中也有相同的请求。 我的GET方法已经有了Access-Control-Allow-Origin头。

我发现AngularJS做出了一个“试用”OPTIONS请求 。 默认情况下,ColdFusion会生成OPTIONS方法,但是它没有太多,特别是这些头文件。 该错误是响应该OPTIONS调用而生成的,而不是我对GET的有意调用。 我在下面的OPTIONS方法添加到我的API后,问题已经解决。

 <cffunction name="optionsMethod" access="remote" output="false" returntype="any" httpmethod="OPTIONS" description="Method to respond to AngularJS trial call"> <cfheader name="Access-Control-Allow-Headers" value="Content-Type,x-requested-with,Authorization,Access-Control-Allow-Origin"> <cfheader name="Access-Control-Allow-Methods" value="GET,OPTIONS"> <cfheader name="Access-Control-Allow-Origin" value="*"> <cfheader name="Access-Control-Max-Age" value="360"> </cffunction> 

我有以下configuration,在请求来自服务器的响应时导致相同的错误。

服务器端: SparkJava – >提供REST-API
客户端: ExtJs6 – >提供浏览器呈现

服务器端,我不得不把这个添加到响应中:

 Spark.get("/someRestCallToSpark", (req, res) -> { res.header("Access-Control-Allow-Origin", "*"); //important, otherwise its not working return "some text"; }); 

客户端,我不得不这个添加到请求中:

 Ext.Ajax.request({ url: "http://localhost:4567/someRestCallToSpark", useDefaultXhrHeader: false, //important, otherwise its not working success: function(response, opts) {console.log("success")}, failure: function(response, opts) {console.log("failure")} }); 

基于shruti的回答 ,我创build了一个Chrome浏览器的快捷方式,并带有必要的参数: 在这里输入图像描述 在这里输入图像描述

如果你正在使用Entity Framework ,那么即使你启用了CORS ,这个错误有时也会被抛出。 我发现由于查询缺失而导致发生错误。 我希望这会帮助其他人在相同的情况。

下面的代码可以抛出XMLHttpRequest cannot load http://myApiUrl/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. XMLHttpRequest cannot load http://myApiUrl/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. 错误:

 using (DBContext db = new DBContext()) { return db.Customers.Select(x => new { Name = x.Name, CustomerId = x.CustomerId, }); } 

为了解决这个问题,需要在查询结尾使用如.ToList().FirstOrDefault()的结束调用,如下所示:

 using (DBContext db = new DBContext()) { return db.Customers.Select(x => new { Name = x.Name, CustomerId = x.CustomerId, }).ToList(); } 

在我的情况下,我正在使用JEE7 JAX-RS应用程序,下面的技巧完美的为我工作:

 @GET @Path("{id}") public Response getEventData(@PathParam("id") String id) throws FileNotFoundException { InputStream inputStream = getClass().getClassLoader().getResourceAsStream("/eventdata/" + id + ".json"); JsonReader jsonReader = Json.createReader(inputStream); return Response.ok(jsonReader.readObject()).header("Access-Control-Allow-Origin", "*").build(); } 

https://github.com/Rob–W/cors-anywhere/提供(Node.js)代码,您可以使用它来设置和运行您自己的CORS代理。; 它被主动维护,并且提供了许多控制代理行为的function,而不仅仅是基本发送正确的Access-Control-*响应头。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS详细解释了浏览器如何处理客户端Web应用程序使用JavaScript创build的跨源请求,以及您必须configuration哪些标头请求的服务器,如果可以的话。;

如果您需要请求并获取响应的站点不会返回Access-Control-Allow-Origin响应头,则浏览器将始终阻止您的客户端直接向其发出的跨域请求从工作的JavaScript代码。 因此,如果网站不是您控制的,并且可以configuration行为,那么在这种情况下唯一可行的就是代理请求 – 可以通过您自己运行的代理或通过开放代理进行代理。

正如在这里的其他评论中所提到的那样,有充分的理由不信任你的请求的开放代理。 也就是说,如果你知道自己在做什么,而且你决定一个开放的代理可以满足你的需求,那么https://cors-anywhere.herokuapp.com/就是一个可靠的,可以被主动维护的,并且运行一个https://github.com/Rob–W/cors-anywhere/代码。;

和其他一些在这里提到的开放代理(其中有几个似乎不再可用)一样,它的工作方式是代替客户端代码直接发送请求到http://foo.com发送到https://cors-anywhere.herokuapp.com/http://foo.com ,代理将必要的Access-Control-*标题添加到浏览器看到的响应中。

您可以通过使用YQL通过雅虎的服务器代理请求来绕过这个问题。 这只是几行代码:

 var yql_url = 'https://query.yahooapis.com/v1/public/yql'; var url = 'your api url'; $.ajax({ 'url': yql_url, 'data': { 'q': 'SELECT * FROM json WHERE url="'+url+'"', 'format': 'json', 'jsonCompat': 'new', }, 'dataType': 'jsonp', 'success': function(response) { console.log(response); }, }); 

以下是链接的解释: https : //vverma.net/fetch-any-json-using-jsonp-and-yql.html

很多时候,这发生在我从JavaScript到我的PHP API,因为几个原因之一。 我忘记把<?php header('Access-Control-Allow-Origin: *'); ? <?php header('Access-Control-Allow-Origin: *'); ? 是一个。 这对跨子域访问很有帮助。 另一个原因,是因为在jQuery ajax请求中,我指定了一个特定的数据types并返回一个不同的数据types,所以会引发错误。

这个错误的最后一个也是最突出的推理是你正在请求的页面上有一个分析错误。 如果您在浏览器中点击该页面的url,则可能会看到parsing错误,并且您将有一个行号来解决该问题。

我希望这可以帮助别人。 我花了一段时间来debugging,我希望我有一个核对清单的事情。

我成功地能够使用htaccess来解决(在我的情况下为字体),但显然,OP是要求有点不同。 但是,您可以使用FileMatch模式并添加任何types的扩展,以便它不会给交叉错误。

 <IfModule mod_headers.c> <FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font.css|css)$"> Header set Access-Control-Allow-Origin "*" </FilesMatch> </IfModule> 

https://httpd.apache.org/docs/2.4/mod/core.html#filesmatch

我在Angular的$http.get中遇到了这个错误。 我需要使用$http.jsonp来代替。

热门问题 – 如果你已经读了这么多,没有别的帮助,还有一件事要看。 如果您有CDN(如Akamai,Limelight或类似软件),则可能需要检查您拥有的资源URI的caching键。 如果它不包含Origin头部值,则可能会返回从另一个Origin请求时caching的响应。 我们只花了半天的时间来debugging。 CDNconfiguration已更新为仅包含我们的一些选定域的“来源”值,并将其设置为空。 这似乎工作,并允许来自我们已知域的浏览器查看我们的资源。 当然,所有其他的答案是先到先得,但如果CDN是您的浏览器的第一跳,这是审查的东西。

在我们的案例中,我们可以看到一些请求提供给我们的服务,但是几乎没有这个网站发送的数量。 这指出了CDN。 我们能够回头看到原始请求是由直接请求提供的,而不是浏览器AJAX调用的一部分,并且不包括响应头Access-Control-Allow-Origin。 显然CDNcaching了这个值。 CDNconfiguration调整来考虑原始请求标头值似乎已经使其工作。

CORS是给你的。

CORS是“跨源资源共享”,是一种发送跨域请求的方式。 现在XMLHttpRequest2和Fetch API都支持CORS。

但它有其局限性。 服务器需要具体声明Access-Control-Allow-Origin ,并且不能设置为“*”。

如果你想要任何起源可以发送请求给你,你需要JSONP(也需要设置访问控制允许起源 ,但可以是'*')。

如果你不知道要选什么,那么对于很多请求方式,我认为你需要一个function齐全的组件来做到这一点。 让我来介绍一个简单的组件catta


如果您使用的是现代浏览器(> Internet Explorer9,Chrome,Firefox,Edge等),则build议您使用一个简单但美观的组件,即https://github.com/Joker-Jelly/catta 。 它没有依赖关系,小于3 KB,它支持Fetch,Ajax和JSONP,使用相同的简单的语法和选项。

 catta('./data/simple.json').then(function (res) { console.log(res); }); 

它也支持一路导入到你的项目,比如ES6模块,CommonJS甚至HTML中的<script>

对于Opera (它和Chrome一样 ),我用这个命令启动了浏览器:

 opera --user-data-dir="~/Downloads/opera-session" --disable-web-security 

问题已经解决了! 现在,我可以在本地HTML文件(在我的硬盘驱动器上)上工作,并将Ajax请求调用到同一文件中的远程来源。

注意1:你可以给你的主目录中的任何文件夹作为–user-data-dir。

注2:testingDebian 8 (Jessie)/ Opera 39

这是一个截图

当您正常启动(不含上述参数)时,相同的请求将落入错误代码块。

只是提到另一种“绕过”它的方式 – AJAX代理。 向您的服务器发送请求以从其他来源获取数据并将请求发回给您。

我比JSONP更喜欢这种方法,因为它有一些潜在的安全问题。

在我的网站上(基于.NET),我刚刚添加了这个:

 <system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Headers" value="Content-Type" /> <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" /> </customHeaders> </httpProtocol> </system.webServer> 

非常感谢这个video。

我已经解决了这个问题,通过启用CORS访问Web API的客户端URL,并成功地运行。

例如:

 [EnableCors(origins: "http://clientaccessingapi.com", headers: "*", methods: "*")] 

对于application_controller.rb Ruby on Rails服务器,添加以下内容:

 after_action :cors_set_access_control_headers def cors_set_access_control_headers headers['Access-Control-Allow-Origin'] = '*' headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS' headers['Access-Control-Allow-Headers'] = '*' end 

也许你可以将资源从生产服务器复制到开发服务器,并让资源的urldynamic调整。 这样你就可以始终从相同的原点读取,消除了交叉原点的exception。

如果您从浏览器中收到此错误消息:

 No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '…' is therefore not allowed access 

when you're trying to do an Ajax POST/GET request to a remote server which is out of your control, please forget about this simple fix:

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

What you really need to do, especially if you only use JavaScript to do the Ajax request, is an internal proxy who takes your query and send it through to the remote server.

First in your JavaScript, do an Ajax call to your own server, something like:

 $.ajax({ url: yourserver.com/controller/proxy.php, async:false, type: "POST", dataType: "json", data: data, success: function (result) { JSON.parse(result); }, error: function (xhr, ajaxOptions, thrownError) { console.log(xhr); } }); 

Then, create a simple PHP file called proxy.php to wrap your POST data and append them to the remote URL server as a parameters. I give you an example of how I bypass this problem with the Expedia Hotel search API:

 if (isset($_POST)) { $apiKey = $_POST['apiKey']; $cid = $_POST['cid']; $minorRev = 99; $url = 'http://api.ean.com/ean-services/rs/hotel/v3/list?' . 'cid='. $cid . '&' . 'minorRev=' . $minorRev . '&' . 'apiKey=' . $apiKey; echo json_encode(file_get_contents($url)); } 

By doing:

 echo json_encode(file_get_contents($url)); 

You are just doing the same query but on the server side and after that, it should works fine.

Answer copied and pasted from NizarBsb

Please add dataType: 'jsonp' in the Ajax function and it works. (:


    $.ajax({
      键入:“POST”,
      dataType: 'jsonp',
      success: function(response) {
        alert("success");
       },
      error: function(response) {
        console.log(JSON.stringify(response));
       }
     });