浏览器出于安全性的考虑,受到javasript的同源策略的影响,不允许调用其他页面的对象.使得A页面无法调用非同源的BURL的iframe ajax应用.
简单的来说,URL符合以下三个条件之一
1.url的域名相同(或ip相同)
2.应用服务的端口号相同
3.相关的协议相同
由协议/端口造成的跨域问题前端无解,只有域名不同产生的跨域可以解决
1.动态的创建标签/jsonp跨域
思路:前端创建script标签,设置src,添加到head里,服务端返回一个js变量的jsonp,这个jsonp就是请求的返回的数据,回调完毕后,删除相应的script标签,并清理一些不必要的内存空间
前端
后端 以php处理为例 url:http://127.0.0.1/demo2/kuayu/data.php?callback=getdata
$callback=$_GET['callback']; //执行回调的js函数
echo $callback."('this is jsonp');";
注意:
2.通过修改html文档中的域 (document.domain)
如果遇到主域相同,但是子域不同的情况,我们可以通过修改document.domain来进行跨域
下面举一个例子:a.test.com/demo3/a.html去请求 test.com/demo3/b.html
通过将两个页面的原始域为相同的
a.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
body>
<script>
document.domain = 'test.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://a.test.com/demo2/b.html';
document.body.appendChild(ifr);
ifr.onload = function(){
var doc = ifr.contentDocument || ifr.contentWindow.document;
alert(doc.getElementById('but').value);
};
script>
html>
b.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<button id="but" value="this is b.html">button>
body>
<script>
document.domain = 'test.com';
script>
html>
3.使用location.hash跨域
首先改变域名的hash不会导致页面刷新,可以通过动态创建一个iframe标签,修改父页面的hash,来实现跨域
下面展示一个例子
http://test.com/demo2/cs1.html去请求http://a.test.com/demo2/cs2.html的数据
由于chrome IE的安全限制,二个非同域的页面无法相互修改hash值,所以在这个需要用到一个跟cs1.html同域的代理页面
cs1.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
body>
<script>
var ifr = document.createElement('iframe');
ifr.style.display = 'none';
ifr.src = 'http://a.test.com/demo2/cs2.html';
document.body.appendChild(ifr);
var data = location.hash ? location.hash.substring(1) : '';
console.log('The data is from '+data);
script>
html>
cs2.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
body>
<script>
try {
parent.location.hash = 'b.html';
} catch (e) {
var ifrproxy = document.createElement('iframe');
ifrproxy.style.display = 'none';
ifrproxy.src = 'http://test.com/demo2/cs3.html#b.html'; // 注意该文件在"test.com"域下
document.body.appendChild(ifrproxy);
}
script>
html>
cs3.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
body>
<script>
parent.parent.location.hash = self.location.hash.substring(1);
script>
html>
这个方法缺点十分明显
1.数据暴露在url中
2.数据传输的大小有限,本身url的长度就有限制
4.使用window.name进行跨域
window其中的name属性是一个浏览器窗口中的共享值,其中所有的页面都共享这个值.首先,将要传输的内容放在请求页面的window.name中,不同的浏览器的对其的内容长度限制不一样,chrome,可以达到2M. 利用iframe加载请求页面,加载完毕后更换iframe的资源路径,换为与当前页面同源的url(也可以是about:blank),就可以获取请求页面中的window.name了,这样既安全,又绕过浏览器的跨域限制.
下面举一个例子
http://test.com/demo2/a.html 去请求http://a.test.com/demo2/b.html
a.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
body>
<script>
var iframe = document.createElement('iframe');
iframe.src = 'http://a.test.com/demo2/b.html';
iframe.οnlοad=function(){
iframe.contentWindow.location = "about:blank";
iframe.οnlοad=function(){
var data = iframe.contentWindow.name; // 读取数据
alert(data);
}
}
document.body.appendChild(iframe);
script>
html>
b.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
body>
<script>
window.name = 'The data is from b';
script>
html>
5.使用HTML5 postMessage
h5的新标准增加了一个新的功能 跨文档消息传输Cross Document Messaging
现代主流浏览器都已经实现这个功能
例如 http://localhost/demo3/a.html和http://127.0.0.1/demo3/b.html的相互通讯
a.html
<iframe src="http://127.0.0.1/demo3/b.html" id="b">iframe>
<script>
window.οnlοad=function(){
var biframe=document.getElementById('b');
biframe.contentWindow.postMessage("hello world","http://127.0.0.1");
}
script>
b.html
<script>
window.addEventListener('message',function(event){
if(event.origin == 'http://localhost')
alert(event.data); // a页面的hello world
},false)
script>
**ps:**contentWindow.postMessage(); 中的参数,第一个是要传送的数据(string) ,第二个请求的域