请求的资源未包含'Access-Control-Allow-Origin'头部信息,因此来自'...'的源被禁止访问。

139
我正在使用 .htaccess 重写 URL 并使用 html base 标签使其生效。
现在,当我尝试进行 AJAX 请求时,出现以下错误:
XMLHttpRequest 无法加载 http://www.example.com/login.php。请求的资源上未提供 'Access-Control-Allow-Origin' 头。因此,不允许来自 http://example.com 的访问。

1
没事了...现在它正常工作了,我甚至不知道错在哪里 :S - Th3lmuu90
8
虽然微小,但 http://wordicious.com 是与 http://www.wordicious.com/ 不同的域名,因此出现了错误。顺便说一下,如果它现在能够正常工作并且自动恢复了,你应该删除这个问题。 - acdcjunior
@acdcjunior,这似乎是错误,你的观察很敏锐。如果您将其发布为答案,我会点赞的。 - Waleed Khan
5
很幸运这个问题没有被删除,否则我今天就看不到它了! - icedwater
11个回答

170

使用addHeader代替使用setHeader方法。

response.addHeader("Access-Control-Allow-Origin", "*");

*在上面的行中将允许访问所有域


为了只允许访问特定域名

response.addHeader("Access-Control-Allow-Origin", "http://www.example.com");

请查看此博客文章


4
它显示了"addheader未定义"。你能解释一下吗? - Vaisakh Pc
9
这些行应该放在哪里? - DaveWalley
14
这应该加在哪里? - Alex
1
那篇博客文章在谈论Node.js和express,而不是客户端JavaScript。有人能确认这是否有效吗? - Sam Eaton
1
这适用于Spring Boot和Java。对于PHP,是header('Access-Control-Allow-Origin: *');。这是一个服务器端解决方案,而不是客户端,对于那些询问的人来说。如果有人真的想使用CORS,最好允许特定域名的访问,但我不建议这样做。最好实现一个API或Web服务,并在自己的应用程序中调用它。 - user2035693
显示剩余5条评论

147

为什么会出现错误:

JavaScript代码受同源策略的限制,这意味着在www.example.com页面上,您只能对位于完全相同域的服务进行(AJAX)请求,在这种情况下,正是www.example.com不是没有wwwexample.comwhatever.example.com)。

在您的情况下,您的Ajax代码正在尝试从位于http://www.wordicious.com的页面中访问http://wordicious.com中的服务。

虽然非常相似,但它们不是相同的域。当它们不在同一域时,只有目标响应包含Access-Control-Allow-Origin头部时请求才会成功。

由于您的页面/服务在http://wordicious.com从未配置过此类头,因此显示该错误消息。

解决方案:

如上所述,JavaScript 所在的源(页面所在的位置)和目标(JavaScript 正试图到达的位置)域必须是完全相同的
您的情况似乎是一个打字错误。看起来http://wordicious.comhttp://www.wordicious.com实际上是同一个服务器/域。因此,要修复问题,请将目标和源输入相等:让您的 Ajax 代码请求页面/服务到 http://www.wordicious.com 而不是 http://wordicious.com。(也许可以将目标 URL 相对地放置,例如'/login.php',没有域名)。



总的来说:

如果问题不像这个问题一样是打字错误,解决方案将是向目标域添加Access-Control-Allow-Origin。要添加它,当然取决于该地址背后的服务器/语言。有时工具中的配置变量可以解决问题。其他时候,您需要自己通过代码添加标题。


62

对于.NET服务器,可以在web.config中进行配置,如下所示:

 <system.webServer>
   <httpProtocol>
     <customHeaders>
       <add name="Access-Control-Allow-Origin" value="your_clientside_websiteurl" />
     </customHeaders>
   </httpProtocol>
 </system.webServer>

例如,假设服务器域名为http://live.makemypublication.com,客户端为http://www.makemypublication.com,则在服务器的web.config中进行如下配置:

 <system.webServer>
   <httpProtocol>
     <customHeaders>
       <add name="Access-Control-Allow-Origin" value="http://www.makemypublication.com" />
     </customHeaders>
  </httpProtocol>
 </system.webServer>

23

如果你从浏览器获得了以下错误信息:

请求的资源上没有 'Access-Control-Allow-Origin' 头。因此,来源 '...' 不被允许访问

当你试图对一个不在你控制范围之内的远程服务器进行 Ajax POST/GET 请求时,请忘记这个简单的修复方法:

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

如果你只使用JavaScript来进行Ajax请求,那么你真正需要做的是设置一个内部代理,将你的查询发送到远程服务器。

首先在你的JavaScript中,进行一个Ajax调用到你自己的服务器,类似于:

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

接下来,创建一个简单的PHP文件,名为proxy.php,用于包装您的POST数据,并将它们作为参数附加到远程URL服务器上。我给出了一个例子,说明如何通过 Expedia 酒店搜索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));
 }

通过这样做:

 echo json_encode(file_get_contents($url));

你只需在服务器端执行同一查询,之后就应该可以正常工作。


@NizarBsb 你知道吗,你太疯狂了!!! :D,非常感谢你的回答,救了我的一命。 - Flash

10

您需要在您的PHP页面 "login.php" 的开头添加此代码

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

6
绝对不安全。 - callback

7

你需要将头部的键/值对放在选项方法响应中。例如,如果你有一个位于http://mydomain.com/myresource的资源,则在服务器代码中编写如下:

//response handler
void handleRequest(Request request, Response response) {
    if(request.method == "OPTIONS") {
       response.setHeader("Access-Control-Allow-Origin","http://clientDomain.com")
       response.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
       response.setHeader("Access-Control-Allow-Headers", "Content-Type");
    }



}

3
将以下内容添加到你的PHP文件或主控制器中。
header("Access-Control-Allow-Origin: http://localhost:9000");

完成最后一步 - 您还需要 header("Access-Control-Allow-Credentials: true"); - Adam

3

这个问题能否在Apache或Nginx配置层面上解决呢?例如,如果用户正在访问mysite.com(没有www),而XHR正在请求www.mysite.com,那么htaccess或httpd.conf指令能否解决这个问题? - codecowboy
当然,您的前端应用程序应该表现为反向代理。例如对于Apache,您必须安装mod_proxy,并使用ProxyPassReverse配置您的规则(http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypassreverse)。Nginx似乎也具有相同的功能:http://wiki.nginx.org/LikeApache - hzrari

3

基本上,通过添加以下附加参数来修改API头响应。

Access-Control-Allow-Credentials:true

Access-Control-Allow-Origin:*

但是,当涉及到安全时,这并不是一个好的解决方案。


1
使用以下条目在httpd.conf中解决:
#CORS Issue
Header set X-Content-Type-Options "nosniff"
Header always set Access-Control-Max-Age 1728000
Header always set Access-Control-Allow-Origin: "*"
Header always set Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT,PATCH"
Header always set Access-Control-Allow-Headers: "DNT,X-CustomHeader,Keep-Alive,Content-Type,Origin,Authentication,Authorization,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control"
Header always set Access-Control-Allow-Credentials true

#CORS REWRITE
RewriteEngine On                  
RewriteCond %{REQUEST_METHOD} OPTIONS 
#RewriteRule ^(.*)$ $1 [R=200,L]
RewriteRule ^(.*)$ $1 [R=200,L,E=HTTP_ORIGIN:%{HTTP:ORIGIN}]]

在Apache2、CentOS7、Laravel 5和React上,对我有效的唯一方法是... - Shakiba Moshiri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接