由于浏览器具有同源策略的限制,当我们想要访问不同源的资源或者数据的时候就会受到限制。比如 ee.bb.com想要访问cc.nihao.com里面的数据就会被拒绝访问。此时就需要解决跨域的问题,一般解决跨域有以下几种方式:
1、服务器代理中转
同源策略只是浏览器的一个限制,但是对后台没有影响,所以可以通过与ee.bb.com同源的
服务器去访问cc.nihao.com里的数据.
2、document.domain(针对基础域名相同的情况)
document.domain只适用于基础域名相同的情况。比如jl.dd.com和sz.dd.com 此种跨域
方式需要分别在jl.dd.com和sz.dd.com中设置document.domain:
jl.dd.com document.domain='dd.com';
sz.dd.com document.domain='dd.com';
3、JSONP
利用jsonp实现跨域的主要原理是:
1.Web页面上用<script> 引入js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥
有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>)
2.于是我们把数据放到服务器上,并且数据最好为json形式(因为js可以轻松处理json数据)
3.事先定义好用于处理跨域获取数据的函数,如 function doJSON(data){}。
4.因为我们无法监控通过<script>的src属性是否把数据获取完成,所以可以在创建script标签
且给src赋值时需要将用于处理获取数据的函数的函数名以参数形式传到服务端,比如可在src上
添加参数cb='doJSON',服务端会将参数cb的值与要返回的数据拼接成函数执行的形式,比如:
doJSON(数据)
例如:
<script>
var script = document.createElement('script');
script.src = 'http://aaa.cc.com?cb=doJSON';
document.body.appendChild(script);
//用于处理跨域获取数据的函数
function doJSON(data){
console.log(data);
}
</script>
4、iframe
iframe就是一个标签,可以在一个网页中嵌套另一个页面。一般主要用来广告植入、在线编辑等。但是iframe也有它的缺点,比如会阻塞页面加载。window 的 onload 事件需要在所有 iframe 加载完毕后(包含里面的元素)才会触发。通过 JavaScript 动态设置 iframe 的 src 可以避免这种阻塞情况
首先来了解一下iframe的一些基本操作:
1.获取iframe内的window
var iframeWindow = document.getElementsByTagName('iframe')[0].contentWindow;
var iframe = window.frames['index2'];//window.frames['iframe的name'];
//IE6 IE7的写法
var ieIframe1 = document.frames['index2'].contentWindow;
var ieIframe2 = document.frames[0].contentWindow;
2.子窗口获取父级窗口 window.parent 顶级窗口 window.top
3.判断iframe是否加载完成
非ie下使用onload事件
iframe(dom元素).onload = function () {}
ie下使用onreadystatechange或者设定计时器
iframe.onreadystatechange = function(){
if (iframe.readyState == 'complete' || iframe.readyState == 'loaded'){
console.log("Local iframe is now loaded.");
}
}
脚本试图访问的框架内容必须遵守同源策略,并且无法访问非同源的window对象的几乎所有属性。同源策略同样适用于子窗体访问父窗体的window对象。解决方式有document.domain、location.hash(解决子页面访问父页面数据的问题)、window.name(解决父页面访问子页面数据的问题)以及html5中的postMessage
1)window.name:解决父页面访问子页面的数据问题
window.name的特点是在当前窗口不关闭的情况下,无论是页面重载刷新还是换了一个页面,name值都不变。
//主页面
var ifr = document.getElementsByTagName('iframe')[0];
var flag = true;
ifr.onload = function () {
if (flag) {
//proxy.html代理文件,一般是一个没有任何内容的html文件需要和主页面在同一域下
ifr.src = './proxy.html';
flag = false;
} else {
console.log(ifr.contentWindow.name)
}
}
//子页面
window.name = 'data';
具体可参考
2)location.hash:解决子页面访问父页面数据的问题
这里主要是利用锚点的特性,改变hash值不会刷新页面。可以在父页面将数据以hash值的方式传递,但是子页面需要监控hash值的变化
//主页面
var ifr = document.getElementsByTagName('iframe')[0];
var num = 12;
var src = ifr.src;
document.onclick = function(){
num++;
ifr.src = src + '#' + num;
}
//子页面
window.onhashchange = function () {
console.log(location.hash.slice(1))
}
///如果不支持hashchange事件,需要利用定时器监控
var lastHash = location.hash;
setInterval(function () {
if (lastHash != location.hash) {
console.log(location.hash.slice(1));
lastHash = location.hash;
}
}, 100)
location.hash缺点
1、传递数据量有限
2、不太安全
3)postMessage
语法:otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow:对接收信息页面的window的引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
message:想要传递的数据
targetOrigin:指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI
/*
* A窗口的域名是<http://example.com:8080>,以下是A窗口的script标签下的代码:
*/
var ifr = document.getElementById('ifr');
var targetOrigin = 'http://example.org';
ifr.contentWindow.postMessage('I was there!', targetOrigin);
function receiveMessage(event)
{
// 我们能相信信息的发送者吗? (也许这个发送者和我们最初打开的不是同一个页面).
if (event.origin !== "http://example.org")
return;
// event.source 是我们通过window.open打开的弹出页面 popup
// event.data 是 popup发送给当前页面的消息
}
window.addEventListener("message", receiveMessage, false);
/*
* B窗口的域名是<http://example.org>
*/
window.addEventListener('message', function(event){
// 通过origin属性判断消息来源地址
if (event.origin == 'http://example.com:8080') {
event.source.postMessage("YEAH" , event.origin);
}
}, false);
参考地址:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
5、CORS
此方法主要是服务端进行配置首部字段,如
Access-Control-Allow-Origin: http://aa.com
Access-Control-Allow-Methods: <method>[, <method>]*
参考地址:
1.https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
2.https://www.cnblogs.com/loveis715/p/4592246.html
6、Flash
关于flash跨域问题可以参考
https://blog.csdn.net/lcg_ryan/article/details/42007443
http://www.cnblogs.com/AS30/archive/2012/09/21/2696788.html