CORS跨域问题
-
CORS是什么
CORS是一个W3C标准,全称为"跨域资源共享"(Cross-origin-resource sharing),
它允许浏览器向跨源服务器,发出
XMLHttpRequest
请求,从而克服ajax只能同源使用的限制 -
简介
CORS需要浏览器和服务器同时支持,目前,所有浏览器均支持该功能,IE浏览器不能低于IE10.
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。(真实),写项目时考虑了很久CORS跨域怎么在前端发送请求时解决,知乎,优快云,简书,b站找了很多资料,都没有找到合适的,最后告诉后端,让他改一下,结果立即好了。
-
两种请求
-
简单请求
浏览器直接发出CORS请求,即在请求头中,增加一个
Origin
字段eg:
GET/cors HTTP/1.1 Origin:http://api.a.com Host:api.alice.com Accept-Language:en-US Connection:keep-alive User-Agent:Mozilla/5.0....
-
Origin
字段,本次请求的来源(协议+域名+端口),服务器根据这个值,进而判断是否同意此次请求-
若
Origin
指定的源,不在许可范围内,服务器会返回一个正常的Http回应,当浏览器检测出响应头信息不包含
Access-Control-Allow-Origin
字段,即说明请求出错,抛出错误,被XHR的onerror
回调函数捕获,无法通过状态码识别,Http响应的状态码可能为200 -
若
Origin
指定的源,在许可范围内,服务器返回的响应头
xxxxxxxxxx Access-Control-Allow-Origin:http://api.a.comAccess-Control-Allow-Credentials:trueAccess-Control-Expose-Headers:FooBarAccess-Type:text/html;charset=utf-8
Access-Control-Allow-Origin
,必需,值为请求时Origin
字段的值,或是通配符*
,表示接受任意域名的请求Access-Control-Allow-Credentials
,可选,值是一个布尔值,表示是否允许发送cookie,默认,Cookie 不包括在CORS请求中,值为true时,表示服务器明确许可Cookie可包含在请求头中,一起发给服务器
Access-Control-Expose-Headers
,可选,CORS请求时,
XHR
的对象的getResponseHeader()
方法只能拿到6个基本字段:Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,若想拿到其他字段,需在Access-Control-Expose-Headers
里面指定
-
-
withCredentials
属性 -------------- cookie跨域CORS 跨域请求默认不发送cookie与HTTP认证信息,若要把Cookie发送到服务器,需要注意的是,
Access-Control-Allow-Origin
不能设置为通配符*
,必须指定明确的、与请求网页一致的域名,同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie
也无法读取服务器域名下的Cookie。一方面需要服务器同意,指定
Access-Control-Allow-Credentials
字段另一方面,在ajax请求中需要设置
var xhr = new XMLHttpRequest(); xhr.withCredentials = true;
如果省略
withCredentials
设置,有的浏览器还是会一起发送Cookie。这时,可以显式关闭withCredentials
。xhr.withCredentials = false;
-
request load 与 FormData()
requeset load 是ajax发送数据是json格式
var param = {
"id":id.value,
"count":count.value
}
var xhr = new XMLHttpRequest();
xhr.onreadystatechange(){
if(xhr.readystate==4 && xhr.status==200){
var jsonObj = xhr.responseText;
var jsonText = JSON.parse(jsonObj);
callBack(jsonText)
}
}
xhr.open("POST/GET","http:///..../a.com");
xhr.setRequestHeader("Content-Type","application/json");
xhr.send(JSON.stringify(param));
formData 格式发送 ajax 请求
var param = "id="+id.value+"&count="+count.value;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange(){
if(xhr.readystate==4 && xhr.status==200){
var jsonObj = xhr.responseText;
var jsonText = JSON.parse(jsonObj);
callBack(jsonText)
}
}
xhr.open("POST/GET","http:///..../a.com");
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(param);
有一次项目,未和后台交流好发送格式,前端发送的是formData格式的数据,但是后台只能接受json格式的数据,返回状态码为415,发送的ajax请求数据格式一定要与后台接收数据的格式一致