CORS: 跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不一样源服务器上的指定的资源。当一个资源从与该资源自己所在的服务器不一样的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。html
出于安全缘由,浏览器限制从脚本内发起的跨源HTTP请求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头。web
origin: web的origin 被定义为由协议,域和端口组成的 URL访问。仅当协议,域和端口所有匹配,两对象才具备相同的origin。shell
Access-Control-Allow-Origin: 该响应是否能够与来自给定的请求代码共享origin。 segmentfault
Access-Control-Allow-Origin:* #容许任何源的代码访问资源 Access-Control-Allow-Origin: https://developer.mozilla.org #容许请求来自https://developer.mozilla.org 的代码访问资源。
Access-Control-Allow-Methods: 在对preflight request(预检请求)的应答中明确了客户端所要访问的资源容许使用的方法或方法列表跨域
Access-Control-Allow-Methods POST,GET,OPTIONS,PUT
Access-Control-Allow-Headers: 用于preflight request(预检请求)种,列出了将会在正式请求的Access-Control-Expose-Headers 字段中出现的首部信息,用于响应包含在Access-Control-Request-Headers 首部的预检请求。浏览器
Access-Control-Allow-Headers Content-Type,access-control-allow-credentials,access-control-allow-origin
Access-Control-Max-Age: 这个响应首部表示preflight request(预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 能够被缓存多久。缓存
Access-Control-Max-Age: 600 #
CORS中的预检请求(option): 在 CORS 中,可使用 OPTIONS 方法发起一个预检请求(通常都是浏览检测到请求跨域时,会自动发起),以检测实际请求是否能够被服务器所接受。预检请求报文中的 Access-Control-Request-Method首部字段告知服务器实际请求所使用的 HTTP 方法;Access-Control-Request-Headers 首部字段告知服务器实际请求所携带的自定义首部字段。服务器基于从预检请求得到的信息来判断,是否接受接下来的实际请求。安全
OPTIONS /resources/post-here/ HTTP/1.1 Host: bar.other Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive Origin: http://foo.example Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER, Content-Type
服务器所返回的 Access-Control-Allow-Methods 首部字段将全部容许的请求方法告知客户端。该首部字段与 Allow 相似,但只能用于涉及到 CORS 的场景中。服务器
想要了解更多的http header信息 请访问 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headerscookie
Access to XMLHttpRequest at 'http://foo1.example.com/' from origin 'http://foo2.example.com/' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
解决方法: 在域为foo1.example.com 的虚拟主机添加 Access-Control-Allow-Origin 值为http://foo2.example.com。
server { ... server_name foo1.example.com; ... add_header 'Access-Control-Allow-Origin' 'http://foo2.example.com'; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; if ($request_method = "OPTIONS") { return 204; } ... }
Access to XMLHttpRequest at 'http://foo1.example.com/' from origin 'http://foo3.example.com/' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'http://foo2.example.com/' that is not equal to the supplied origin.
解决方法:请注意观察上述报错, Access-Control-Allow-Origin 已经至少有一个值为http://foo2.example.com 的设定。因此如今配置一个容许多源访问的配置。
server { ... server_name foo1.example.com; ... if ( $http_origin ~ .*.(example|aldwx).(net|com)) { set $other_domain $http_origin; } add_header Access-Control-Allow-Origin $other_domain; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; if ($request_method = "OPTIONS") { return 204; } ... }
Access to XMLHttpRequest at 'http://foo1.example.com/' from origin 'http://foo2.example.com/' has been blocked by CORS policy: Request header field <u>cookies</u> is not allowed by Access-Control-Allow-Headers in preflight response.
解决方法: 遇到这一类的问题时,须要仔细阅读报错,在报错里面基本已经写明了答案。例如上面的这个报错信息。域foo2.example.com 请求域foo1.example.com 时,因首部cookies 未包含在 Access-Control-Allow-Headers 中,因此foo1没法响应客户端请求。而且这一类问题可能同时会出现几个首部缺失的请求,可是报错是单个出现,因此呢,要仔细阅读错误。下面也是其中一个报错
Access to XMLHttpRequest at 'http://foo1.example.com/' from origin 'http://foo2.example.com/' has been blocked by CORS policy: Request header field <u>access-control-allow-credentials</u> is not allowed by Access-Control-Allow-Headers in preflight response.
server { ... server_name foo1.example.com; ... if ( $http_origin ~ .*.(example|aldwx).(net|com)) { set $other_domain $http_origin; } add_header Access-Control-Allow-Origin $other_domain; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers 'access-control-allow-credentials,cookies,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; if ($request_method = "OPTIONS") { return 204; } ... }