web前端跨域方案
ajax跨域请求 qzfl实现
跨子域的xhr
- 原生xhr不支持跨域,通过iframe+proxy.html达到跨子域
- 假如A页面要请求B页面,A、B跨子域。A创建指向B的proxy页的iframe,将目的url、回调方法挂在iframe属性上,proxy通过frameElement获取目的url发送xhr请求后回调由A页面设置在iframe上的回调方法达到代理请求的目的。
跨全域的get请求jsonp
- jsonp可以跨全域,但只支持get方式。利用的是script标签没有域名限制的特性
跨全域的post请求formSend
- 通过构造带form表单的iframe,并将回调方法挂在iframe,提交form产生post请求,调用frameElement.callback回调。需要cgi返回符合协议格式
<html> <head><meta http-equiv="Content-Type" content="text/html;charset=gb2312" /></head> <body><script type="text/javascript"> document.domain="qq.com"; frameElement.callback({JSON:"Data"}); </script></body> </html>
下载源码:qzfl_2.1.27.js
xhr2.0
HTML5的XMLHttpRequest 2.0 在旧浏览器支持的XMLHttpRequest对象升级后,且向前兼容。
如何判断是否支持XHR 2.0?
网页端
new XMLHttpRequest().withCredentials==="undefined" 有withCredentials属性则支持XMLHttpRequest 2.0。
如果是使用jquery,ajax参数要设置下
$.ajaxSetup({ // dataType: 'json', xhrFields: {withCredentials: true} });
服务器端
例如PHP:header('Access-Control-Allow-Origin: http://someotherdomain.com');
withCredentials 默认为false,不会发送目标域名的cookie。手动设为true后,且服务器Access-Control-Allow-Credentials
设置为true时,则可发送和接受到目标域名的cookie。
header('Access-Control-Allow-Origin: http://qgroup.qq.com'); header("Access-Control-Allow-Credentials: true");
XHR2.0的新特性?
1.可发送跨域(子域)请求,在请求头中携带Origin属性,这个属性由浏览器生成无法修改。用来给服务器判断来源是否合法。
2.XHR的新接口api在保持向前兼容的同时,更简洁实用。
XMLHttpRequest(.upload)--onload、onerror、onabort、onprogress =fn 上传请求和返回响应阶段都可以定义回调方法,特别是onprogress是完全新增的功能
xhr.upload.onprogress=function(e){
e.loaded/e.total
}
3.支持二进制数据,xhr.send(ArrayBuffer/Bolb)
跨域通信
postMessage+navigator方式
iframe跨域通信在高级浏览器上可以通过html5 postMessage接口实现,在ie6、7下可以通过navigator共享来解决。
postMessage通信
A主页面要跟B iframe嵌入页面通信
A.js:
document.getElementById("B").contentWindow.postMessage(data,domain);
B.js:
B.addEventListener("message",callbackB,true);
B iframe页面要跟A主页面通信
B.js:
window.top.postMessage(data,domain);
A.js:
window.addEventListener("message",callbackA,true);
window.name方式
实现跨域主动拉取页面数据,页面数据应该是无状态的静态数据。
事例:A页面存有一个UI组件的dom、js、css,B页面非同域情况下要获取A的ui组件信息我们通常会用<script>方式,但这一script里要包含html和css格式会很难看,通过A页面将UI数据存在window.name中,B页面创建 iframe先请求A页面获取window.name值后跳转到about:blank页,因为每个域名下都有个about:blank页面,这样B就能取得window.name,间接与A通信成功了。
但这种业务场景比较特殊,适用不广泛。参考链接:http://www.cnblogs.com/rubylouvre/archive/2012/07/30/2614904.html