【问题标题】:Access-Control-Allow-Origin server mods are not workingAccess-Control-Allow-Origin 服务器模块不起作用
【发布时间】:2017-08-07 21:22:13
【问题描述】:

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

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 配置中的标头以允许我的 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. 启动带有标志 --disable-web-security 的 Chrome 允许我进行测试,并且我的网站和代码在 Chrome 中运行良好。

  2. 但是,这揭示了另一个奇怪的问题,即如果我尝试将 add_header 行添加到位置指令,我的无网络安全 Chrome 和我未修改的 Safari 都无法从我的 api 加载信息。所以现在我不确定服务器块中的 add_header 指令是否正常工作。

如果有帮助,这是我的客户端代码(包括我尝试过/注释掉的内容):

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 来自服务器的最新响应(尽管我已经打开和关闭了各种选项客户端和服务器,例如凭据并将来源更改为完全是我的或 * 无济于事):

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 不允许的原始错误,即使它们工作正常并且没有对服务器配置进行任何更改。今晚我会喝得酩酊大醉……

【问题讨论】:

  • 您的 nginx 配置看起来正确。请更新您的问题,以在添加 add_header Access-Control-Allow-Headers Authorization 行后包含您在浏览器开发工具控制台中看到的确切错误消息。
  • 就像我上面说的,它只是恢复到原来的Origin not allowed 消息。
  • enable-cors.org/server_nginx.html 显示了 nginx 的完整 CORS 配置设置应该是什么样子。您可能想尝试尽可能地遵循这一点。不幸的是,您的问题中没有足够的细节能够知道,但是由于您的请求中存在 Authorization 标头,因此浏览器将对 OPTIONS 请求返回的响应中可能会发生一些问题。 (假设请求中有一个 Authorization 标头-无法确定,因为您的问题原样没有提供有关请求的详细信息……)
  • 谢谢,但我试过了(甚至在标题列表中添加了授权),结果与上面完全相同,唉。
  • 您应该删除xhr.setRequestHeader('Access-Control-Allow-Origin','http://home.mydomain.org')。 Access-Control-Allow-Origin 严格来说是服务器发送的响应标头。从客户端将其作为请求标头发送的唯一影响是使 CORS 预检失败。同样的事情或注释掉的//xhr.setRequestHeader('Access-Control-Allow-Credentials', 'true')。 Access-Control-Allow-Credentials 是严格的响应头,所以你绝对不想取消注释。

标签: wordpress nginx cors wordpress-rest-api


【解决方案1】:

哇,这太令人费解了。在这里发布答案,以防其他一些 WP 用户在这里找到他们的方式。我不断得到不一致的结果(有时有效,有时并不神秘),最后我的问题是在服务器上的 PHP 代码中设置的标头,独立于 nginx 设置,有时与它们相矛盾(尽管从来没有以我可以预测的方式看)。所以我需要解决的问题是:

  • 删除了我的 nginx 配置中的所有 cors 声明
  • 我的服务器上还有用于验证 auth 标头中的令牌的代码,但它在 OPTIONS 预检时失败(它永远不应该检查),所以我必须先添加一个 if 语句才能让它忽略一个 OPTIONS 调用( !$_SERVER['REQUEST_METHOD'] === "OPTIONS")
  • 由于我使用 UpdraftPlus 插件从我的另一个站点克隆了该站点,因此我不得不删除我的迁移密钥,因为它们的存在也阻止了 api 调用的工作。删除它们后,我的通话又开始工作了。
  • 删除并重新添加了内置的 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 中)!

【讨论】:

    猜你喜欢
    • 2011-09-13
    • 2021-01-01
    • 2017-08-29
    • 1970-01-01
    • 2018-01-01
    • 2021-09-16
    • 2015-05-02
    • 2013-10-27
    • 2019-02-13
    相关资源
    最近更新 更多