为什么我在这里看到“访问控制 - 允许来源不允许的来源”错误?

问题描述:

我看到下面的错误:为什么我在这里看到“访问控制 - 允许来源不允许的来源”错误?

Origin http://localhost:8080 is not allowed by Access-Control-Allow-Origin 

与此代码:

var http = new getXMLHttpRequestObject(); 
var url = "http://gdata.youtube.com/action/GetUploadToken"; 
var sendXML = '<?xml version="1.0"?><entry xmlns="http://www.w3.org/2005/Atom"'+ 
    'xmlns:media="http://search.yahoo.com/mrss/'+ 
    'xmlns:yt="http://gdata.youtube.com/schemas/2007">'+ 
    '<media:group><media:title type="plain">My First API</media:title>'+ 
    '<media:description type="plain">First API</media:description>'+ 
    '<media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">People</media:category>'+ 
    '<media:keywords>first, api</media:keywords></media:group></entry>'; 
http.open("POST", url, true); 
http.setRequestHeader("Authorization", "AuthSub token=" + AccessToken); 
http.setRequestHeader("X-GData-Key", "key="+ dev_key); 
http.setRequestHeader("Content-Type", "application/atom+xml; charset=UTF-8"); 

http.onreadystatechange = function() { 
    if(http.readyState == 4) { 
     alert(http.responseXML); 
    } 
} 
http.send(sendXML); 

,是什么原因?我该如何解决呢?

+1

您确定您使用的YouTube入口点是否启用了jsonp?除非使用服务器端代理或jsonp endpont,否则无法对外部域进行ajax调用。 – andreapier 2012-02-16 11:07:36

在当前域之外进行ajax请求时,Javascript受到限制。

  • 例1:你的域名是example.com,你想向test.com发出一个请求=>你不能。例如:
  • 例2:你的域名是example.com,你想向inner.example.com发出一个请求=>你不能。
  • 例3:你的域名是example.com:80,你想向example.com:81 =>请求
  • EX 4:你的域名是example.com,你想提出请求以example.com =>你可以。

出于安全原因,Javascript受“同源策略”限制,因此恶意脚本无法联系远程服务器并发送敏感数据。

jsonp是使用javascript的不同方法。您提出请求并将结果封装到客户端运行的回调函数中。这与把一个新的脚本标签链接到你html头部的相同(你知道你可以从这里加载不同于你的域的脚本)。
但是,要使用jsonp,必须正确配置服务器。如果不是这种情况,你不能使用jsonp,你必须依靠服务器端代理(PHP,ASP等)。有很多与此主题相关的指南,只是谷歌它!

+1

谢谢!我不知道这会发生在同一台主机上,但在不同的端口。 – ViniciusPires 2013-06-27 00:42:54

+0

我可以使用AmplifyJS发送到不同的域吗? – Misi 2013-07-25 06:51:09

+0

我从来没有使用AmplifyJS我不知道。如果它只是一个JavaScript库(如jQuery),我非常怀疑你可以避免jsonp。如果它也有服务器部分,它仍然是可能的。我不能说更多,对不起。 – andreapier 2013-07-27 09:51:13

由于“相同来源策略”,XMLHttpRequest不会让您达到localhost:8080

您可以通过localhost:8080添加标题您的回复让现代浏览器的请求:

Access-Control-Allow-Origin: * 

您可以通过添加指令到你的HTTP服务器或添加通过服务器端代码头(PHP这样做, Ruby,...)。

了解更多关于跨来源Ajax请求的https://developer.mozilla.org/en/http_access_control

+14

如果我正确理解这一点,那么API或远程资源(在本例中为YouTube服务器)的服务器必须设置标题,即它必须设置此标头的API主机,而不是API调用方。 – 0x4a6f4672 2012-05-23 13:15:37

+1

@ 0x4a6f4672正确! – Sunny 2012-07-13 14:39:41

+2

还有其他人发现这令人困惑吗?使用Fiddler我可以看到正在发出的请求以及正在返回的有效结果...然后发生异常。所以服务器似乎并不在乎。然而,服务器是需要配置的服务器? – 2013-05-15 14:21:27

如果您使用的是Chrome,一个简单的解决方法(仅用于开发目的)是使用选项--disable-web-security

+50

您当然只_only_想为发展目的做什么,_never_在冲浪时 – kynan 2012-07-27 20:35:00

+0

同意@kynan并更新了我的答案。 – Deqing 2012-11-27 14:07:21

+0

希望我今天早些时候知道。对于生产部署,我们使用Nginx,因此最容易处理CORS头文件,或者它们可能位于相同的域:端口。它只适用于我想绕过它的本地开发。 – felix 2013-07-05 13:46:54

无关的这个特定的问题,但对于使用jQuery ...这个错误也造成如果您尝试使用jQuery做一个JSONP请求,并省略魔术回调参数在这种情况下,任何人:callback=?

+1

魔术参数也可以有其他名称。文档:http://api.jquery.com/jQuery.getJSON/#jsonp – Gruber 2012-12-14 10:07:07

添加global.asax在你的解决方案中。

添加

HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); 

protected void Application_BeginRequest(object sender, EventArgs e) 
{ 
} 
+0

为什么人们不喜欢这个?这是在ASP.net中实现这一点的一种方法 – Layinka 2014-12-15 19:10:59

+0

我试过了,但没有奏效。仍然得到错误。使用MVC5 – 2016-05-10 06:36:13

如果你是从Java后台一个可能的解决办法是让这对你的JavaScript调用Web服务的servlet。类似于GET(Your-choice)方法中的以下代码...

JsonElement jelement; 
    JsonArray jarray; 
    try { 
     URL url = new URL("http://rest."YOUR URL"#ba0482"); 
     URLConnection connection = url.openConnection(); 
     connection.setDoInput(true); 
     InputStream inStream = connection.getInputStream(); 
     BufferedReader input = new BufferedReader(new InputStreamReader(inStream)); 

     jelement = new JsonParser().parse(input); 

     jarray = jelement.getAsJsonArray(); 

     response.setContentType("application/json"); 
     PrintWriter out = response.getWriter(); 
     out.print(jarray); 
     out.flush(); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

现在,在JavaScript中只需指定url作为servlet名称!

对于本地开发,您可以使用工具来修改HTTP响应头。例如Charles能够通过附带的重写工具来做到这一点:Rewrite Tool

只是添加新的规则为目标域/位置:

Type: Add Header 
Where: Response 
Replace 
    Name: Access-Control-Allow-Origin 
    Value: * 
Replace All 

如果您使用Apache,这个工程:把这个/在您的公共根目录下创建一个.htaccess文件,并添加您可能需要的任何其他文件扩展名。

<FilesMatch "\.(ttf|otf|eot|woff|jpg|png|jpeg|gif|js|json|html|css)$"> 
    <IfModule mod_headers.c> 
    Header set Access-Control-Allow-Origin "*" 
    </IfModule> 
</FilesMatch> 

如果重新使用谷歌浏览器的浏览器,您可以添加CORS的扩展,并激活它,它会解决空洞问题,而不必在你的代码进行任何更改

我碰到了同样的错误消息,当使用Ajax来访问一个PHP页面(JavaScript和PHP文件都位于同一台服务器上)。

原因是我在我的JavaScript中指定了IP地址作为域。这使浏览器相信,调用PHP文件是在另一台服务器上。

所以一个简单的解决方案来摆脱这个错误信息。 a)验证javascript和php文件在同一台服务器上 b)确保JavaScript(例如http://www.smartana.co.uk/myJavaScript.js)ajax中的url(尤其是域)反映了您的服务器url(例如http://www.smartana.co.uk/myServer.php)。

在这里,我们需要为Apache HTTP

1)做两件事情在httpd.config文件中,取消该文件

LoadModule headers_module modules/mod_headers.so 

2)在底部添加此行。

Header set Access-Control-Allow-Origin "*"