Access-Control-Allow-Origin 服务器模组不工作

Access-Control-Allow-Origin server mods are not working

我很难让我的服务器接受来自另一台服务器(本地,但在我的主机文件中给出了域名)的请求,而不会触发可怕的

XMLHttpRequest cannot load https://dev.mydomain.org/api/user?uid=1. Origin http://home.domain.org is not allowed by Access-Control-Allow-Origin.

我的开发服务器(互联网)是 运行 nginx,我的家庭服务器(本地)是 运行 apache。

我试过网上的几种解决方法,都没有用。我尝试修改 nginx 配置中的 headers 以允许我的 home.mydomain.org 服务器,我还在本地添加了 htaccess 规则以允许所有来源 (*)。

我的 nginx 服务器块目前有这些行:

   add_header Access-Control-Allow-Origin http://home.mydomain.org; 
   add_header Access-Control-Allow-Headers Authorization;

仅添加第一行确实稍微改变了我的响应(从简单的 Origin not allowed by Access-Control-Allow-OriginRequest header field Authorization is not allowed by Access-Control-Allow-Headers.),但添加第二行只是将错误恢复为原始错误,我仍然被阻止。

此时,我不确定还能尝试什么。

更新:

  1. 使用标志启动 Chrome --disable-web-security 允许我进行测试,我的站点和代码在 Chrome.

    中运行良好
  2. 然而,这揭示了另一个奇怪的问题,即如果我尝试将 add_header 行添加到位置指令,我的 no-web-security Chrome 和我未经修改的 Safari 无法从我的 api 加载信息。所以现在我不确定服务器块中的 add_header 指令是否正常工作。

如果有帮助,这是我的客户端代码(包括我已经 tried/commented 的东西):

var xhr = new XMLHttpRequest();
var self = this;
xhr.open('GET', apiURL + self.currentIssue);
xhr.setRequestHeader('Access-Control-Allow-Origin','http://home.mydomain.org');
//xhr.setRequestHeader('Access-Control-Allow-Credentials', 'true');
xhr.withCredentials = true;
//xhr.setRequestHeader('Access-Control-Request-Method','*');
xhr.setRequestHeader('Authorization','Bearer longstringoflettersandnumbers');
xhr.onload = function () {
        self.posts = JSON.parse(xhr.responseText);
        };
xhr.send();

尝试以下建议后的另一个更新: 在客户端和服务器上反复试验之后,我仍然卡住了。这是我使用 curl 从服务器得到的最新响应(尽管我已经打开和关闭各种选项客户端和服务器,例如 Credentials 和更改 origin 完全是我的或 * 无济于事):

HTTP/1.1 204 No Content Server: nginx Date: Sun, 06 Aug 2017 10:11:57 GMT Connection: keep-alive Access-Control-Allow-Origin: http://home.mydomain.org Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: GET, POST, OPTIONS Access-Control-Allow-Headers: Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range Access-Control-Max-Age: 1728000 Content-Type: text/plain; charset=utf-8 Content-Length: 0

这是我的控制台错误 (Safari):

[Error] Origin http://home.mydomain.org is not allowed by Access-Control-Allow-Origin.
[Error] Failed to load resource: Origin http://home.mydomain.org is not allowed by Access-Control-Allow-Origin. (actions, line 0)
[Error] XMLHttpRequest cannot load https://dev.mydomain.org/api/user?uid=1 due to access control checks.

这是我的 Firefox 控制台错误:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://dev.mydomain.org/api/user?uid=1. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

同样在 Firefox 中,以下是 OPTIONS 和 GET 网络面板的结果:

Request URL: https://dev.mydomain.org/api/user?uid=1
Request method: OPTIONS
Status code: 204 No Content
Version: HTTP/2.0

Response headers (511 B)    
Server  "nginx"
Date    "Sun, 06 Aug 2017 10:44:22 GMT"
Access-Control-Allow-Origin "http://home.mydomain.org"
access-control-allow-credentials    "true"
Access-Control-Allow-Methods    "GET, POST, OPTIONS"
Access-Control-Allow-Headers    "Authorization,DNT,X-CustomHea…ent-Type,Content-Range,Range"
Access-Control-Max-Age  "1728000"
Content-Type    "text/plain; charset=utf-8"
Content-Length  "0"
X-Firefox-Spdy  "h2"
Request headers (501 B) 
Host    "dev.mydomain.org"
User-Agent  "Mozilla/5.0 (Macintosh; Intel… Gecko/20100101 Firefox/54.0"
Accept  "text/html,application/xhtml+x…lication/xml;q=0.9,*/*;q=0.8"
Accept-Language "en-US,en;q=0.5"
Accept-Encoding "gzip, deflate, br"
Access-Control-Request-Method   "GET"
Access-Control-Request-Headers  "authorization"
Origin  "http://home.mydomain.org"
Connection  "keep-alive"
Cache-Control   "max-age=0"


Request URL: https://dev.mydomain.org/api/user?uid=1
Request method: GET
Status code: 404 Not Found
Version: HTTP/2.0

Response headers (170 B)    
Server  "nginx"
Date    "Sun, 06 Aug 2017 10:44:22 GMT"
Content-Type    "text/html"
Vary    "Accept-Encoding"
Content-Encoding    "gzip"
X-Firefox-Spdy  "h2"
Request headers (723 B) 
Host    "dev.mydomain.org"
User-Agent  "Mozilla/5.0 (Macintosh; Intel… Gecko/20100101 Firefox/54.0"
Accept  "*/*"
Accept-Language "en-US,en;q=0.5"
Accept-Encoding "gzip, deflate, br"
Referer "http://home.mydomain.org/"
Authorization   "Bearer eyJ0eXAG…BRHmX9VmtYHQOvH7k-Y32wwyeCdk"
Origin  "http://home.mydomain.org"
Connection  "keep-alive"
Cache-Control "max-age=0"

部分成功的更新:

我想我发现了问题(部分):将我在 nginx 中的位置指令从 location /api 更改为 location = /api/* 使其正常工作!但仅适用于 Safari 和 Chrome,FF 现在甚至不尝试 GET 请求,网络面板中没有它的条目。

更新时哭泣、咬牙切齿和扯头发 Safari 和 Chrome 间歇性地失败,并显示原始错误,不允许 Origin,即使它们工作正常并且没有对服务器配置进行任何更改。我今晚会喝很多...

哇,这真是令人费解。在这里发布答案以防其他 WP 用户在这里找到他们的方式。我一直得到不一致的结果(有时工作,有时不神秘)并最终将我的问题追踪到 headers 在服务器上的 PHP 代码中设置,独立于 nginx 设置,有时与它们相矛盾(尽管从来没有以我能看到的可预测方式)。所以我需要解决的事情是:

  • 删除了我的 nginx 配置中的所有 cors 声明
  • 我的服务器上也有代码验证 auth header 中的令牌,它在 OPTIONS 预检时失败(它永远不应该检查)所以我必须在之前添加一个 if 语句它忽略 OPTIONS 调用 (!$_SERVER['REQUEST_METHOD'] === "OPTIONS")
  • 因为我使用 UpdraftPlus 插件从我的另一个站点克隆了这个站点,所以我不得不删除我的迁移密钥,因为它们的存在也阻止了 api 调用的工作。一旦它们被删除,我的电话又开始工作了。
  • 删除并 re-added 内置 WP 过滤器 rest_pre_serve_request

我的过滤器代码在这里:

add_action('rest_api_init', function() {
/* unhook default function */
remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');   
/* then add your own filter */
add_filter('rest_pre_serve_request', function( $value ) {
$origin = get_http_origin();
$my_sites = array( $origin ); // add array of accepted sites if you prefer
if ( in_array( $origin, $my_sites ) ) {
header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) );
} else {
header( 'Access-Control-Allow-Origin: ' . esc_url_raw( site_url() ) );
}
header( 'Access-Control-Allow-Methods: OPTIONS, GET, POST, PUT, PATCH, DELETE' );
header( 'Access-Control-Allow-Credentials: true' );
header('Access-Control-Allow-Headers: Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Origin,Content-Type,X-Auth-Token,Content-Range,Range');
header('Access-Control-Expose-Headers: Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Origin,Content-Type,X-Auth-Token,Content-Range,Range');
header( 'Vary: Origin' );
return $value;
});
}, 15);

现在终于,一切都可以在任何地方运行(在每个浏览器和 curl 中也是如此)!