目录javascript
Keywords CORS, 跨域,JS跨域调用,Ajax CORS 跨域,跨域详解,CORS跨域原理css
Cross-Origin Resource Sharing 一般简称为:CORS。它是一种机制,这个机制使用了一个额外的HTTP响应头来赋予当前user-agent(浏览器)得到在当前源(origin)下使用非同源资源的权限。这句话听起来很拗口,不易理解。可是请注意加粗字体所标记的两个关键字,这里的非同源就是Cross-Origin的概念,这里边的权限就是访问非同源的资源权限。下面咱们弄清楚了这两个关键字的概念就理解了什么是Cross-Origin Resource Sharing。html
假设咱们如今在浏览器中输入 http://www.myapp.com/index.html 请求index.html页面。index.html中有一些文字信息,有一张图片
http://www.somecloud.com/images/a.jpg ,和一个css文件 http://www.somecnd.com/a.css 。同时index.html的script节点中有以下的一个JavaScript方法。那么,图片、样式是否可以正常显示,getCrossRescource方法是否能正常执行呢?java
function getCrossRescource () { $.ajax({ url:"http://www.other.com/goods.json", success:function(){ // do something } }); }
以chrome浏览器为例,假设咱们开发者工具,而后在浏览器中输入上面的连接,咱们能够看到,图片正常显示,样式也正常渲染。可是getCrossRescource ()方法并未执行成功。咱们在开发者工具的制台面板里边会看到错误信息:web
Failed to load :http://www.other.com/goods.jsonajax
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.myapp.com is therefore not allowed access.chrome
经过错误信息咱们得知:由于请求的资源不容许当前源https://www.myapp.com 访问,由于没有Access-Control-Allow-Origin头信息,为何呢?json
这是由于:出于安全的缘由,浏览器限制从脚本内发起跨源的HTTP请求,也就意味着限定了当前web应用程序只能请求与当前同域(同源)的HTTP资源,除非使用CORS头信息。——原来被浏览器限制了。那么那些请求会被限制呢?canvas
- 以跨站点的方式调用XMLHttpRequest或者Fetch API。
- Web字体(用于CSS中@ font-face的跨域字体使用)
- WebGL textures
- 使用drawImage绘制到canvas的图像/视频帧。
- 样式表(用于CSSOM访问)
能够看到XMLHttpRequest遵循这个规则,而咱们一般所使用的ajax方法就是基于XMLHttpRequest来实现的,因此在没有使用CORS头信息的的状况,跨源的getCrossRescource ()方法天然会没法顺利执行。而上文所提到的index.html里跨源的a.jpg、a.css不属于拦截目标,因此可以正常显示和渲染。跨域
说到这里咱们弄清楚了机制的问题。这个机制约定了同源的问题,并阻止了规定的这些请求形式。还剩下一个同源的概念须要解释,那么什么叫作同源,什么叫作非同源呢?
给定两个页面,若是它们的协议、端口(若是指定了端口)、host都相同,则称之为同源。如今给出一个源链接和一些其余链接与这个源的比较,结合下表,咱们来实际的理解一下这个概念。
http://store.company.com/dir/page.html
:
URL | 是否同源 | 缘由 |
---|---|---|
http://store.company.com/dir2/other.html | 是 | |
http://store.company.com/dir/inner/another.html | 是 | |
https://store.company.com/secure.html | 否 | 协议不一样 |
http://store.company.com:81/dir/etc.html | 否 | 端口不一样 |
http://news.company.com/dir/other.html | 否 | host不一样 |
以上文中的例子来讲明,咱们访问的是 http://www.myapp.com/index.html 页面,那么当前的origin就是 http://www.myapp.com。 而这个页面中的脚步请求的资源是 http://www.other.com/goods.json ,根据上文介绍的信息咱们能够得知:这个是非同源的请求,且属于浏览器拦截名单里边的请求形式。因此咱们须要经过设置CROS头信息来完成跨域调用。
本例中,咱们须要在http://www.other.com/goods.json所对应的服务器代码中加入响应头:
Access-Control-Allow-Origin: http://www.myapp.com
设置完以后,当前的源http://www.myapp.com得到了访问数据的权限。这个时候咱们能够在请求/响应头信息看到多了一些信息,大体以下:
GET /... Host: ... User-Agent: ... Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive Referer: http://www.myapp.com/index.html Origin: http://www.myapp.com -------------------------- HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 00:23:53 GMT Server: Apache/2.0.61 Access-Control-Allow-Origin: http://www.myapp.com Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: application/xml
除了使用设置CORS头信息,咱们还可使用JSONP来实现跨域调用。以Jquery为例,咱们可使用以下的写法来调用跨域资源:
function corsTest(){ $.ajax({ type: "get", url: "http://other.host/data.json", dataType:"jsonp", jsonp:"callback", jsonpCallback:"callBack", ...... }) } function callBack(data){ // do something ...... }