深层
在下面的调查中,我使用http://example.com作为API地址,而不是你提出的http://myApiUrl/login,因为前者可用。我假设你的页面位于http://my-site.local:8088。
注意:API和你的页面拥有不同的域名!
你看到不同的结果的原因是Postman:
- 设置头部
Host = example.com
(你的API)
- 未设置头部
Origin
- Postman实际上根本不使用你的网站URL(你只是在Postman中键入API地址),他只发送请求到API,所以他认为网站的地址与API相同(浏览器不会这么认为)
这类似于当站点和API具有相同域时浏览器发送请求的方式(浏览器也设置了头部项Referer=http://my-site.local: 8088
,但我在Postman中没有看到它)。 当 Origin
头部未设置时,通常服务器默认允许此类请求。
这是Postman发送请求的标准方式。但是,当你的站点和API具有不同的域名时,浏览器会以不同的方式发送请求,然后CORS出现,并自动:
- 设置头部
Host=example.com
(为API)
- 设置头部
Origin=http://my-site.local:8088
(为你的站点)
(头部Referer
的值与Origin
相同)。现在在Chrome的控制台和网络选项卡中,你将看到:
当你的Host!= Origin
时,这是CORS,当服务器检测到这样的请求时,通常会默认阻止它。
Origin=null
表示在从本地目录打开HTML内容并发送请求时设置的值。当您在<iframe>
内发送请求时,也会出现相同的情况,就像下面的代码片段中一样(但此处根本未设置Host
标头) - 通常,在HTML规范中说不透明来源的任何地方,您都可以将其翻译为Origin=null
。有关更多信息,请访问此处。
fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab
如果您不使用简单的CORS请求,通常浏览器在发送主要请求之前会自动发送OPTIONS请求 - 更多信息请参见这里。下面的片段展示了它:
fetch('http://example.com/api', {
method: 'POST',
headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)
您可以更改服务器配置以允许CORS请求。
这是一个示例配置,用于在nginx上启用CORS(nginx.conf文件) - 在设置nginx的 always / "$http_origin"
和Apache的" * "
时要非常小心 - 这将解除对任何域的CORS阻止(在生产中,使用消耗API的具体页面地址而不是星号)。
location ~ ^/index\.php(/|$) {
...
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
}
以下是一个示例配置,可以在 Apache 上启用 CORS(.htaccess 文件)
# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests |
# ------------------------------------------------------------------------------
# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/
# <IfModule mod_headers.c>
# Header set Access-Control-Allow-Origin "*"
# </IfModule>
# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"
Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"