当请求设置了一个特殊的请求头而且所请求的接口并没有配置 Access-Control-Allow-Headers 响应头时,会报如下错误,如demo-3所示:
上面的截图展示了请求附带了一个 X-Custom-Header 的请求头,但是请求在preflight阶段就失败了,如果要让请求成功完成的话,则必须在 OPTIONS 请求的响应里面配上 Access-Control-Allow-Headers: X-Custom-Header 。
Access-Control-Allow-Methods
与上一个 HTTP 头相似, Access-Control-Allow-Methods 告诉浏览器当前接口允许使用哪些 HTTP 方法去请求它。这个 HTTP 头通常也是在 OPTIONS 请求的响应头中才有意义。当没有通过这个响应头时,会报这样的错误:
同样的,上面的截图在preflight阶段就失败了。如果要让请求成功执行的话,那么需要配置响应头为: Access-Control-Allow-Methods: GET,POST,PUT 。
Access-Control-Max-Age
由于 OPTIONS 请求的存在,对于一个非简单请求来说,实际发出去的请求会有两个。这多多少少会浪费带宽,毕竟这个校验应该只会在第一次发生而已,一旦通过校验,在接下来的一段时间里,再次请求该接口的话,那么实际上 OPTIONS 请求则没有必要再发出。
好在,有个叫做 Access-Control-Max-Age 的响应头可以实现这样的功能。这个响应头指定了请求一旦通过了 preflight 请求之后,会在多长时间内无须再次触发preflight请求。从而达到减少实际请求,减少带宽浪费的问题。
Access-Control-Allow-Credentials
默认情况下, 任何跨域请求都不会带上任何身份凭证的,这些身份凭证包括:
然而,在大多数情况下,我们需要请求带上 cookie ,那么则需要开启跨域请求的 withCredentials 选项。
想要手动开启传输 cookie 的话,有以下方法;
开启了 withCredentials 之后卡盟,请求在发出去的时候就会默认加上 Cookie。
然而,除了需要在前端中手动开启 withCredentials 之外,服务器端也需要有相应响应头支持,请求才会成功。
Access-Control-Allow-Credentials 这个响应头则是表明了当前请求的资源是否允许附带身份凭证。当其值为 true 时请求才成功,否则会失败,失败内容如下:
可以参考demo-7观看请求头以及响应头。
另外, 一旦开启了 withCredentials 选项,服务器端的 Access-Control-Allow-Origin 响应头就不能是通配符,只能是固定的一个域名,否则会请求失败。 具体错误内容为:
demo-8和demo-9分别演示了当请求带上 cookie 时,响应头配置为通配符的情况以及响应头有正确配置为具体域名的情况。
总结
总的来说,当在脚本里面发出请求时,会有以下情况:
所请求资源的协议、端口或者域名如果与当前发出请求的页面地址一致,那么则符合同源策略,请求可以被正常发出。反之,则称为跨域请求,需要遵守 CORS 机制。
所有跨域请求里面当前页面的脚本发生错误 为空或不是对象,服务器端必须返回 Access-Control-Allow-Origin 响应头,并且其值与请求中的 Origin 请求头的值相匹配。此时请求才可以被允许,否则请求将会被浏览器拦截掉。