记一次cors预检不通过造成的原因:
这个报错是后端没有响应头没有返回Assess-Control-Allow-Origin字段;
名称
cors 资源共享,cross origin resource sharing。
功能概述
对于内些可能对服务器数据产生副作用的请求, 会先发起一个options的预检请求(preflight request)判断是否允许进行跨域,服务器确认允许之后,才会发起真正的http请求
场景
请求分为简单请求和非简单请求
简单请求
同时满足两大条件是简单请求
条件一:请求方法
- HEAD
- POST
- GET
条件二:请求头字段不超出以下字段
- Accept :指定返回类型,text/plain(纯文本)、text/html(html类型)
- Accept-Language 指定语言
- Content-Language 指定内容语言
- Last-Event-ID
- content-type:指定三个字段
- text/plain 纯文本
- multiple/form-data 上传表单内包含文件
- application/x-www-form-urlencoded 对发送内容进行编码
简单请求包含origin字段(http会默认携带在Request header),代表访问的域名来源
Origin: http://api.bob.com
Host: api.alice.cÏom
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
若服务器检索后发现不在请求范围内,返回一个正常的http响应,但不包含Assess-Control-allow-Origin字段。如果在允许范围内响应头如下:
Access-Control-Allow-Origin: http://api.bob.com 允许访问域名,或者*不限制访问
Access-Control-Expose-Headers:yy
Access-Control-Allow-Credentials:true 表示是否可以发送cookie
Content-Type:text/plain(纯文本内容); charset=utf-8
Access-Control-Expose-Headers:yy
这个字段代表可以从XMLHttpRequest对象的getResponseRequest拿到指定字段的值,亦可用getAllResponseHeaders拿到所有可读字段,如果多个用;分开。否则只能拿到指定的六个字段:content-language、content-type、cache-control、expires、last-modified、pragma
如果想发送cookie是需要服务端和客户端配合的
服务端
Assess-Control-Allow-Credentials:true
客户端:
const xhr = new XMLHttpRequest()
xhr.withCredentials =true;
如果省略withCredentials有的浏览器还是会发送cookie
xhr.withCredentials = false;
简单请求客户端只需发送origin字段后端会进行检索,就可以完成cors跨域请求。
非简单请求
触发非简单请求是不满足简单请求的条件一和条件二。
后端会进行预检请求校验,根据 Assess-Control-Allow-Origin 、Assess-Control-Allow-Method、Assess-Control-Allow-Headers
如果请求不通过就会抛出错误,js是捕捉不到的需要从console里面看。如果OPTIONS请求通过就会和简单请求一样。
总结:
- cors 是资源共享一种解决方案,但是不支持ie10以下
- cors请求分为简单请求和非简单请求
- 简单请求主要通过origin和Assess-Control-Allow-Origin进行校验
- 非简单请求是有触发条件的会根据三个字段进行校验
- 回归最开始的问题,根据报错发现没有对Assess-Control-Allow-Origin进行配置,那么好去找后端进行配置。