cors(全程:跨域资源共享cross-origin-resource-shaw)
实质就是在服务器后台程序中设置允许不同域发送过来的请求。cors存在两种请求方式,简单请求和非简单请求。
一、判断请求是否为跨域请求,当为跨域请求时,判断是否为简单请求或者是非简单请求
1、判断是否为跨域请求
当我们发送请求时,浏览器会检测我们页面所在域名是否与请求链接所在域名为同一域名。若校验为同源,则直接发送请求;若校验为非同源,则会为请求头部添加字段Origin
,值类型为安全协议(http/https)+ 域名(www.baidu.com)代表着自身所在的域名。(即:Origin:http://www.baidu.com
)
2、判断是为简单请求还是非简单请求
当检测为跨域请求时,浏览器就会判断此请求时简单请求还是非简单请求。主要根据两大点。请求方式为head、get、post
;请求头部字段不超过Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
(标注:这点不太懂?何为不超过,有哪些字段算是超过,cookie,User-Agent、Host等算吗?)。肯定答案为简单请求,否定答案为非简单请求。
二、简单请求
注意:只发送正式通信请求,请求次数为一次。
1、请求方式:head、get、put
2、请求过程:服务器就会根据Origin
这个字段获取请求所在域名。当服务器发现此域名不在可允许域名列表内部,则会返回一个正常的http回应,但是浏览器发现响应请求头部没有Access-Control-Allow-Origin
字段,则会发现服务器禁止本域请求,因此会抛出异常;当服务器发现此域名在可允许域名列表内部,也会返回一个正常的http回应,但是服务器会为响应请求头部添加字段Access-Control-Allow-Origin
字段,指明服务器可允许域名列表。
3、请求头部:
字段Origin:值类型为安全协议(http/https)+ 域名(www.baidu.com)代表着自身所在的域名。(即:Origin:http://www.baidu.com
)
4、响应头部:
字段Access-Control-Allow-Origin:值为请求字段Origin或则星号(*),代表服务器可接受域名;字段Access-Control-Allow-Credentials:值为布尔型,代表服务器是否接受cookie;字段Access-Control-Request-Headers:值为自定义字段名,代表服务器会额外发送字段供前端利用getResponseHeader获取。(getResponseHeader(‘selfField’))
三、非简单请求
注意:第一次发送预检请求,第二次发送正式通信请求,请求次数为两次。
预检请求
1、请求方式:options
2、请求过程:浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段(服务器可能存在某些的特殊要求)。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
3、请求头部
字段Origin:值类型为安全协议(http/https)+ 域名(www.baidu.com)代表着自身所在的域名。(即:Origin:http://www.baidu.com
);字段Access-Control-Request-Method:值为GET、POST等请求方式,代表浏览器可接受的请求方式;字段Access-Control-Request-Headers:值为自定义字段名,代表浏览器CORS请求会额外发送的头信息字段。
4、响应头部
字段Access-Control-Allow-Origin:值为请求字段Origin或则星号(*),代表服务器可接受域名;字段Access-Control-Request-Method:值为GET、POST等请求方式,代表服务器可接受的请求方式;字段Access-Control-Request-Headers:值为自定义字段名,代表服务器可接受CORS请求额外发送的头信息字段。
正式通信
排除请求方式与简单请求不同以外,其余部分雷同
1、请求方式:根据服务器要求(字段Access-Control-Request-Method)而定,可能为PUT,又可能为DELETE
四、跨域cookie存储
我们都知道cookie遵循同源策略,那么在cors请求中怎么实现不同域间的cookie通信?
withCredentials 属性
除了在服务器后台中设定字段Access-Control-Allow-Credentials为true外,我们还要在前端发送请求时打开withCredentials属性,设置为true。
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
推荐日志:阮一峰CORS详解