一、同源策略
在了解跨域之前,我们先看看同源策略的知识
同源就是指两个 url 的协议、域名、端口号完全一致,那么这两个 url 就是同源。
同源策略:浏览器规定如果 js 运行在源 a 上,那么就不能获取源 b 的数据,目的是为了保护用户的隐私。
二、跨域
所以我们需要跨域去获取资源,以下是两种解决方案
2.1 CROS
官方解释:
跨域资源共享( CORS )机制允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。
CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。
具体操作:
需要服务端的 response 处设置响应头,然后我方 ajax 请求即可
缺点:
不兼容 ie
response.setHeader("Access-control-Allow-origin", "http:xx对方的urlxxx");
2.2 CROS 两种请求
浏览器将 CORS 请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
2.2.1 简单请求
只要同时满足以下两大条件,就属于简单请求。
- 请求方法是以下三种方法之一:
- HEAD
- GET
- POST
- HTTP 的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain
简单请求,就是在头信息中,增加一个 Origin 字段。 比如下面是一个跨域的 AJAX 请求,自动在头信息中,添加了一个 Origin 字段。
GET /cors HTTP/1.1
Origin: http://api.bb.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
然后服务端的响应头为
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
2.2.2 复杂请求
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是 PUT 或 DELETE,或者 Content-Type 字段的类型是 application/json。
非简单请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,称为"预检"请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的 XMLHttpRequest 请求,否则就报错。
var url = 'http://api.bibi.com/cors';
var xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();
服务器收到"预检"请求以后,检查了 Origin、Access-Control-Request-Method 和 Access-Control-Request-Headers 字段以后,确认允许跨源请求,就可以做出回应。
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bibi.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
如果服务器拒绝预检请求,控制台就会报错
XMLHttpRequest cannot load http://api.cc.com.
Origin http://api.bibi.com is not allowed by Access-Control-Allow-Origin.
2.2 JSONP
JSONP 解决的是在 IE 下,不能用 cors 的方式来共享数据的问题
它的原理是通过< script> 标签引入另一个网站的数据
这时候返回的数据是一个函数譬如:
showData({"name:"bibi","city":"hangzhou"})
所以需要本方设置一个回调函数,然后对方调用
window. showData(data)=>(console.log(data))
JSONP
优点:兼容 ie 并且可以跨域
缺点:因为是 script 引用传送所以不支持 post。