关于跨域的总结
关于跨域,个人总结了以下几种方法
- JSONP
- CORS
- WebSocket
- document.domain
- window.name
- location.hash
- postMessage
其中:CORS、jsonp等方法常用,window.name的方法既不复杂,也能兼容到几乎所有浏览器,这真是极好的一种跨域方法。
webSocket
WebSocket是一种在单个TCP连接上进行全双工通讯的协议。WebSocket与HTTP协议其实两者的关系像是两兄弟,各自有着各自擅长的领域,而且时不时还一同协作解决难题。
WebSocket要解决的问题:当服务器资源到位时,能够主动通知浏览器并返回相应资源。HTML5标准推出了WebSocket协议。
本身就不受浏览器“同源策略”的限制,WebSocket协议下的通讯机制,客户端和服务端一旦建立连接,就可以顺畅的互发数据,因此WebSocket协议本身就是“有状态的”,不需要Cookie的帮忙,既然没有Cookie,自然也不需要“同源策略”去保护。
下面来说说webSocket的具体实现:
像发起AJAX请求一样,发起WebSocket请求需要借助浏览器提供的WebSocket对象,该对象提供了用于创建和管理WebSocket连接,以及通过该连接收发数据的API。所有的浏览器都默认提供了WebSocket对象。让我们看看该对象的用法:
和使用XHRHttpRequest对象一样,我们首先要实例化一个WebSocket对象:
传入的参数为响应WebSocket请求的地址。
同样类似AJAX的是,WebSocket对象也有一个readyState属性,用来表示对象实例当前所处的链接状态,有四个值:
0:表示正在连接中(CONNECTING);
1:表示连接成功,可以通信(OPEN);
2:表示连接正在关闭(CLOSING);
3:表示连接已经关闭或打开连接失败(CLOSED);
我们可以通过判断这个值来执行我们相应的代码。
除此之外,WebSocket对象还提供给我们一系列事件属性,使我们控制连接过程中的通信行为:
onopen:用于指定连接成功后的回调函数;
onclose:用于指定连接关闭后的回调函数;
onmessage:用于指定收到服务器数据后的回调函数;
onerror:用于指定报错时的回调函数;
通过.send()方法,我们拥有了向服务器发送数据的能力(WebSocket还允许我们发送二进制数据)。
如何知道何时我们的数据发送完毕呢?我们需要使用WebSocket对象的bufferedAmount属性,该属性的返回值表示了还有多少字节的二进制数据没有发送出去,所以我们可以通过判断该值是否为0而确定数据是否发送结束。
CORS
阮一峰博客http://www.ruanyifeng.com/blo...
在http header中写入允许访问的域名。
Access-Control-Allow-Origin,该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
需要注意的是:CORS请求默认情况下是不会发送cookie的,所以需要在服务器的响应中设置:
Access-Control-Allow-Credentials: true
除此之外,还需要在AJAX请求中设置:
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
CORS请求分为简单请求和非简单请求:
简单请求:需要AJAX里的onerrer回调函数进行捕获,因为也可能会返回200。
非简单请求:浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
会首先发送一个预检请求,请求方法为:options,并且在请求头中会包含相应字段:
Access-Control-Request-Method
Access-Control-Request-Headers
如果响应头中有CORS相关字段:
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
浏览器检查响应头中包含这三个字段,则预检请求成功;否则,则会抛出错误。一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。
JSONP
- 我们发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>);
- 于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;
- 恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;
- 这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。
- 、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。
- 为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
document.domain
这个主要针对跨域访问cookie的情况
两个网页一级域名相同,只是二级域名不同
,浏览器允许通过设置document.domain共享 Cookie。
举例来说,A网页是http://w1.example.com/a.html,B网页是http://w2.example.com/b.html,那么只要设置相同的document.domain,两个网页就可以共享Cookie。
其实也可以在服务器端进行设置:
指定Cookie的所属域名为一级域名,比如.example.com。
Set-Cookie: key=value; domain=.example.com; path=/
这样二级域名和三级域名不用做任何设置都可以共享这个cookie。
未完待续。。。