为啥我在这里看到“Access-Control-Allow-Origin 不允许来源”错误? [复制]

Posted

技术标签:

【中文标题】为啥我在这里看到“Access-Control-Allow-Origin 不允许来源”错误? [复制]【英文标题】:Why am I seeing an "origin is not allowed by Access-Control-Allow-Origin" error here? [duplicate]为什么我在这里看到“Access-Control-Allow-Origin 不允许来源”错误? [复制] 【发布时间】:2012-03-07 18:46:19 【问题描述】:

我看到以下错误:

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

这是什么原因造成的,我该如何解决?

【问题讨论】:

您确定您使用的 youtube 入口点启用了 jsonp 吗?除非您使用服务器端代理或 jsonp 端点,否则您不能对外部域进行 ajax 调用。 【参考方案1】:

在当前域之外发出 ajax 请求时,javascript 会受到限制。

Ex 1:您的域是 example.com,您想向 test.com 发出请求 => 您不能。 示例 2:您的域是 example.com,您想向 inner.example.com 发出请求 => 您不能。 Ex 3:您的域是 example.com:80,您想向 example.com:81 发出请求 => 您不能 EX 4:您的域是 example.com,您想向 example.com 发出请求 => 可以。

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

jsonp 是使用 javascript 的另一种方式。您发出请求,结果被封装到在客户端运行的回调函数中。这与将新的脚本标记链接到 html 的头部部分相同(您知道您可以在此处从与您的域不同的域加载脚本)。 但是,要使用 jsonp,必须正确配置服务器。如果不是这种情况,则不能使用 jsonp,并且必须依赖服务器端代理(php、ASP 等)。有很多与这个主题相关的指南,只需谷歌它!

【讨论】:

谢谢!我不知道这会发生在同一主机但在不同的端口。 我可以使用 AmplifyJS 发送到不同的域吗? 我从来没有使用过 AmplifyJS,我不知道。如果它只是一个 Javascript 库(如 jQuery),我非常怀疑你是否可以避免使用 jsonp。如果它也有服务器部分,它仍然是可能的。我不能说更多,对不起。 jsonp 不是只对GET 请求有效吗? 在我的情况下,我试图连接到 EF 连接字符串中的不同数据库,导致 CORS 错误(ASP.NET Web API)【参考方案2】:

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

您可以通过在localhost:8080 上的响应中添加标头来允许来自现代浏览器的请求:

Access-Control-Allow-Origin: *

您可以通过向 HTTP 服务器添加指令或通过服务器端代码(PHP、Ruby 等)添加标头来实现。

在https://developer.mozilla.org/en/http_access_control 上阅读有关跨域 ajax 请求的更多信息

【讨论】:

如果我理解正确,那么 API 或远程资源的服务器(在本例中为 YouTube 服务器)必须设置标头,即必须设置此标头的是 API 托管商,而不是API 调用者。 还有其他人觉得这很混乱吗?使用 Fiddler,我可以看到正在发出请求并返回有效结果......然后我得到一个异常。所以服务器似乎根本不在乎。但是服务器是需要配置的吗? 这里服务器不关心。浏览器试图通过仅允许返回服务器允许列表中的请求来保护用户。 需要修改httpd.conf文件还是php.ini文件? @FedericoCapaldo 在这种情况下,您将创建自己的 API,充当代理,将请求转发到原始 API。【参考方案3】:

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

【讨论】:

你肯定想为开发目的而做,从不在冲浪时 同意@kynan 并更新了我的答案。 希望我今天早些时候知道这一点。对于生产部署,我们使用 nginx,因此最容易处理 CORS 标头,或者它们可能位于同一个域:端口上。它仅适用于我想绕过它的本地开发人员。 如何启用它? (如何倒退?)【参考方案4】:

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

添加

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

protected void Application_BeginRequest(object sender, EventArgs e)


【讨论】:

为什么人们不赞成这个?这是在 ASP.net 中实现此目的的一种方法 我试过这个,但没有奏效。仍然收到错误。使用 MVC5 添加“Application_BeginRequest”将允许对 API 的所有方法进行交叉调用。如果我想为单个网络方法做这件事怎么办?【参考方案5】:

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

【讨论】:

【参考方案6】:

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

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

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

【讨论】:

【参考方案7】:

这里,我们需要为 Apache Http 做两件事

1) 在 httpd.config 文件中,取消注释该文件

LoadModule headers_module modules/mod_headers.so

2) 在底部添加这一行。

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

【讨论】:

【参考方案8】:

如果您使用谷歌浏览器作为浏览器,您可以添加 CORS 扩展并激活它,它将解决漏洞问题,而无需更改代码中的任何内容

【讨论】:

【参考方案9】:

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

【讨论】:

魔术参数也可以有其他名称。文档:api.jquery.com/jQuery.getJSON/#jsonp【参考方案10】:

如果您来自 java 背景,一种可能的解决方案是制作一个 servlet,它为您的 javascript 调用 Web 服务。类似于 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 名称!

【讨论】:

【参考方案11】:

我在使用 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)。

【讨论】:

以上是关于为啥我在这里看到“Access-Control-Allow-Origin 不允许来源”错误? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥这里没有生成 Coredump 文件?

为啥我看到 WCF 的性能比 Remoting 慢?

为啥当我在选中 CheckBox 的情况下滚动 ListView 时,它会变为未选中状态?

为啥我在这个程序上听到哔哔声? [复制]

为啥许多 init.d 脚本以“exit $?”结尾?

为啥我在尝试调用 CDHtmlDialog::OnInitDialog() 时看到崩溃