在前端开发中出于种种原因,总会有需要访问其它域名数据的时候.比如说,因为某项业务你需要调用一下第三方的一个接口.或者说你需要与其他域名的网站交互一下数据等等.不一而足.但是,与此同时我们也知道.浏览器在出于安全方面的考虑,有一个同源策略.只要是不同域名,不同端口,不同协议之间的通讯都会被浏览器阻止.而在这个情况下,跨域这个概念也就油然而生了.
什么是跨域
跨域一词从字面意思看,就是跨域名嘛,但实际上跨域的范围绝对不止那么狭隘。具体概念如下:只要协议、域名、端口有任何一个不同,都被当作是不同的域。之所以会产生跨域这个问题呢,其实也很容易想明白,要是随便引用外部文件,不同标签下的页面引用类似的彼此的文件,浏览器很容易懵逼的,安全也得不到保障了就。什么事,都是安全第一嘛。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。所以我们要通过一些方法使本域的js能够操作其他域的页面对象或者使其他域的js能操作本域的页面对象(iframe之间)。下面是具体的跨域情况详解:
URL | 说明 | 是否允许通信 |
---|---|---|
http://www.a.com/a.js | ||
http://www.a.com/b.js | 同一域名下 | 允许 |
http://www.a.com/lab/a.js | ||
http://www.a.com/script/b.js | 同一域名下不同文件夹 | 允许 |
http://www.a.com:8000/a.js | ||
http://www.a.com/b.js | 同一域名,不同端口 | 不允许 |
http://www.a.com/a.js | ||
https://www.a.com/b.js | 同一域名, | 不同协议 不允许 |
http://www.a.com/a.js | ||
http://70.32.92.74/b.js | 域名和域名对应ip | 不允许 |
http://www.a.com/a.js | ||
http://script.a.com/b.js | 主域相同,子域不同 | 不允许(cookie这种情况下也不允许访问) |
http://www.a.com/a.js | ||
http://a.com/b.js | 同一域名,不同二级域名(同上) | 不允许(cookie这种情况下也不允许访问) |
http://www.cnblogs.com/a.js | ||
http://www.a.com/b.js | 不同域名 | 不允许 |
所以简单来说,跨域就是为了避开浏览器的同源策略而使用的一种手段.
CORS
就目前而言,常见的跨域方式有三种,一种是服务器代理,一种是JSONP,还有一种就是我们今天要讲的CORS
.
CORS
也被称为跨域资源共享.他是HTML5推出的对于跨域问题的一个解决方案.也是最正统的解决方案.它几乎不需要我们在配置什么,与普通的XMLHttorequest
请求一样.浏览器在我们发送请求的时候会自动的为我们配置好.只要在服务端支持CORS
就可以正常的跨域访问.
在CORS
之前.所使用的服务器代理和JSONP都是不是标准所支持的.而是我们充满智慧的程序员们另辟蹊径所想出来的解决方案.
什么是CORS
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出
XMLHttpRequest
请求,从而克服了AJAX只能同源使用的限制。
CORS简介
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS
通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS
通信的关键是服务器。只要服务器实现了CORS
接口,就可以跨源通信。
两种请求
在支持CORS
的浏览器中,CORS
请求分为两种.
- 一种是不会触发
CORS
预检的简单请求:
这些跨域请求与浏览器发出的其他跨域请求并无二致。如果服务器未返回正确的响应首部,则请求方不会收到任何数据。因此,那些不允许跨域请求的网站无需为这一新的 HTTP 访问控制特性担心。
只要同时满足以下两大条件,就属于简单请求
1. 请求方法是以下三种方法之一:
HEAD
GET
POST
2. HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
- 一种是会触发
CORS
预检的预检请求
与简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。
只要请求满足下述任一条件时,即为预检请求
- 使用了下面任一 HTTP 方法:
- PUT
- DELETE
- CONNECT
- OPTIONS
- TRACE
- PATCH
- 人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:
- Accept
- Accept-Language
- Content-Language
- Content-Type (but note the additional requirements below)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- Content-Type 的值不属于下列之一:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
服务器设置
- Access-Control-Allow-Origin(必含) – 允许的域名,只能填通配符或者单域名
- Access-Control-Allow-Methods(必含) – 这允许跨域请求的http方法(常见有POST、GET、OPTIONS)
- Access-Control-Allow-Headers(当预请求中包含Access-Control-Request-Headers时必须包含) – 这是对预请求当中Access-Control-Request-Headers的回复,和上面一样是以逗号分隔的列表,可以返回所有支持的头部。
- Access-Control-Allow-Credentials(可选) – 该项标志着请求当中是否包含cookies信息,只有一个可选值:true(必为小写)。如果不包含cookies,请略去该项,而不是填写false。这一项与XmlHttpRequest2对象当中的withCredentials属性应保持一致,即withCredentials为true时该项也为true;withCredentials为false时,省略该项不写。反之则导致请求失败。
- Access-Control-Max-Age(可选) – 以秒为单位的缓存时间。预请求的的发送并非免费午餐,允许时应当尽可能缓存。
CORS的优势
CORS与JSONP的使用目的相同,但是比JSONP更强大。
JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
浏览器兼容性
参考资料
我的个人网址 https://wangyiming.info/