跨域方法
-
跨域问题
-
跨域的形成:主域、子域、ip和域名、协议不同、端口不同
-
常用解决方案
-
iframe+document.domain:适用于垮子域的情况
缺点是如果一个域名下存在安全问题,另一个域名下可能也会有问题,还有就是创建iframe的开销 -
动态引入js脚本:适合所有的跨域场景
引入的脚本会立刻执行,存在安全风险
要与远端沟通约定变量,增加了开发和维护成本 -
iframe+location.hash:适合各种场景下跨域
iframe嵌套引用,开销更大
会产生历史记录,url中暴露传递的内容 -
iframe+window.name:使用iframe的window.name从外域传递数据到本地域,适合各种场景下跨域且数据安全
缺点是数据有大小限制 -
postMessage
跨域通讯页面域关系: - 例子用hash跨域
-
主页面a.html所属域A:www.taobao.com
被iframe的页面b.html所属域B:www.alimama.com,假设地址:http://www.alimama.com/b.html实现效果:
A域名下的页面a.html中通过iframe嵌入B域名下的页面b.html,由于b.html的宽度和高度是不可预知而且会变化的,所以需要a.html中的iframe自适应大小.
问题本质:
js对跨域iframe访问问题,因为要控制a.html中iframe的高度和宽度就必须首先读取得到b.html的大小,A、B不属于同一个域,浏览器为了安全性考虑,使js跨域访问受限,读取不到b.html的高度和宽度.
解决方案:
引入代理代理页面c.html与a.html所属相同域A,c.html是A域下提供好的中间代理页面,假设c.html的地址:www.taobao.com/c.html,它负责读取location.hash里面的width和height的值,然后设置与它同域下的a.html中的iframe的宽度和高度.
代码如下:
a.html代码
首先a.html中通过iframe引入了b.html
<iframe id=”b_iframe” height=”0″ width=”0″ src=”http://www.alimama.com/b.html” frameborder=”no” border=”0px” marginwidth=”0″ marginheight=”0″ scrolling=”no” allowtransparency=”yes” ></iframe>b.html代码
<script type=”text/javascript”>
var b_width = Math.max(document.documentElement.clientWidth,document.body.clientWidth);
var b_height = Math.max(document.documentElement.clientHeight,document.body.clientHeight);
var c_iframe = document.getElementById(”c_iframe”);
c_iframe.src = c_iframe.src+”#”+b_width+”|”+b_height; //http://www.taobao.com/c.html#width|height”
}
</script>
<!–js读取b.html的宽和高,把读取到的宽和高设置到和a.html在同一个域的中间代理页面车c.html的src的hash里面–>
<iframe id=”c_iframe” height=”0″ width=”0″ src=”http://www.taobao.com/c.html” style=”display:none” ></iframe>c.html代码
<script type=”text/javascript”>
var b_iframe = parent.parent.document.getElementById(”b_iframe”);
var hash_url = window.location.hash;
var hash_width = hash_url.split(”#”)[1].split(”|”)[0]+”px”;
var hash_height = hash_url.split(”#”)[1].split(”|”)[1]+”px”;
b_iframe.style.width = hash_width;
b_iframe.style.height = hash_height;
</script>
a.html中的iframe就可以自适应为b.html的宽和高了. -
看了园友的 window.name实现的跨域数据传输
自己实践了一下,真的很好用。
特将具体实现方法记录如下:
如a.com网站想通过JS获取b.com网站的数据。
1 在a.com网站添加一个空HTML页。名称为:http://a.com/null.html
2 在a.com网站需要获取数据页面(如:http://a.com/getDomainData.html)内容如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>跨域获取数据</title> <script type="text/javascript"> function domainData(url, fn) { var isFirst = true; var iframe = document.createElement('iframe'); iframe.style.display = 'none'; var loadfn = function(){ if(isFirst){ iframe.contentWindow.location = 'http://a.com/null.html'; isFirst = false; } else { fn(iframe.contentWindow.name); iframe.contentWindow.document.write(''); iframe.contentWindow.close(); document.body.removeChild(iframe); iframe.src = ''; iframe = null; } }; iframe.src = url; if(iframe.attachEvent){ iframe.attachEvent('onload', loadfn); } else { iframe.onload = loadfn; } document.body.appendChild(iframe); } </script> </head> <body> </body> <script type="text/javascript"> domainData('http://b.com/data.html', function(data){ alert(data); }); </script> </html>
3 在b.com中添加获取数据页面 如:http://b.com/data.html 内容需包含:
<script> window.name = '需要跨域传递的数据'; </script>
4 访问 http://a.com/getDomainData.html 就可返回 http://b.com/data.html 中的window.name中的数据了。
需要注意的地方
null.html 是必须的。内容可为空。
iframe的onload事件绑定 必须这样写:
if(iframe.attachEvent){ iframe.attachEvent('onload', loadfn); } else { iframe.onload = loadfn; }
调用domainData函数必须在body后面,或页面加载完后。
调用时会执行 http://b.com/data.html 页面的脚本。