先说定义,什么是跨域:
对于浏览器而言,只要访问域名、协议、端口中任何一个不同就会引发同源策略。
同源策略就是为了保护用户安全,防止不同域JS交互:
1限制cookie 、localStorage 、indexDB 的读取;
2无法获取DOM信息;
3Ajax请求无法发送。
如何解决跨域问题
1.CORS (跨域资源共享) -- Cross-Origin-Resource-Sharing
原理:使用自定义的HTTP头让浏览器和服务器进行沟通,来判断请求或者相应是否成功;
所以只有在被请求的Reponse header 中加入如下设置即可实现跨域访问:
”Access-Control-Allow-Origin:*“ //指定允许其他域名访问
"Access-Control-Allow-Methods:GET,POST" //响应类型
”Access-Control-Allow-Header:x-requested-with,content-type“ //响应头设置
2.通过Jsonp跨域 - Json with Padding(填充式json)的简写
JSONP的原理:通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。(即用JavaScript动态加载一个script文件,同时定义一个callback函数给script执行而已。)
在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。
3.使用HTML5的window.postMessage方法跨域
HTML5引入了一个新的API:跨文档通信API(Cross-document-message)
这个API里有个叫window.postMessage方法,看名字显而易见了,允许浏览器跨窗口通信,不论这两个窗口是否同源。很牛逼啊!
例如:a.html 向 b.html 发送数据,调用postMessage方法:
a页面:
```
<iframe id="frame1" src="http://127.0.0.1/JSONP/b.html" frameborder="1"></iframe>
document.getElementById('frame1').onload = function(){
var win = document.getElementById('frame1').contentWindow;
win.postMessage("我是来自a页面的","http://127.0.0.1/JSONP/b.html")
}
```
b页面:
```
window.onmessage =function(e){
e = e || event;
console.log(e.data);//我是来自a页面的
}
```
子窗口向父窗口发送消息的写法类似。
```
window.opener.postMessage('我是来自b页面的','http://a.com'); //父窗口和子窗口都可以通过message事件,监听对方的消息。
```
通过window.postMessage,读写其他窗口的 LocalStorage 也成为了可能。
下面是一个例子,主窗口写入iframe子窗口的localStorage。
父窗口发送消息代码:
```
var win = document.getElementsByTagName('iframe')[0].contentWindow;
var obj = { name: 'Jack' };
// 存入对象
win.postMessage(JSON.stringify({key: 'storage', method: 'set', data: obj}), 'http://b.com');
// 读取对象
win.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*");
window.onmessage = function(e) {
if (e.origin != 'http://a.com') return;
// "Jack"
console.log(JSON.parse(e.data).name);
};
```
子窗口接收消息的代码:
```
window.onmessage = function(e) {
if (e.origin !== 'http://bbb.com') return;
var payload = JSON.parse(e.data);
switch (payload.method) {
case 'set':
localStorage.setItem(payload.key, JSON.stringify(payload.data));
break;
case 'get':
var parent = window.parent;
var data = localStorage.getItem(payload.key);
parent.postMessage(data, 'http://aaa.com');
break;
case 'remove':
localStorage.removeItem(payload.key);
break;
}
};
```