JavaScript跨域:
URL | 说明 | 是否允许通信 |
http://www.a.com/a.js | 同一域名下 | 允许 |
http://www.a.com/lab/a.js | 同一域名下不同文件夹 | 允许 |
http://www.a.com:8000/a.js | 同一域名,不同端口 | 不允许 |
http://www.a.com/a.js | 同一域名,不同协议 | 不允许 |
http://www.a.com/a.js | 域名和域名对应ip | 不允许 |
http://www.a.com/a.js | 主域相同,子域不同 | 不允许 |
http://www.a.com/a.js | 同一域名,不同二级域名(同上) | 不允许(cookie这种情况下也不允许访问) |
http://www.cnblogs.com/a.js | 不同域名 | 不允许 |
JavaScript请求了不属于自己所在域的资源,违反了同源策略,由此产生跨域。
跨域的分类:
(1)协议不同,比如http和https。
(2)域名或ip不同。
(3)端口不同。
跨域解决方案:
1、script标签跨域方案。
Script标签并无同域策略限制,是可以跨域获取脚本文件的。
客户端代码:
<!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">
var result = null;
window.onload = function () {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://192.168.0.101/ExampleBusinessApplication.Web/web2.aspx";
var head = document.getElementsByTagName("head")[0];
head.insertBefore(script, head.firstChild);
};
function callback(data) {
result = data;
}
function b_click() {
alert(result.name);
}
</script>
</head>
<body>
<input type="button" value="click me!" onclick="b_click();" />
</body>
</html>
服务端代码:
protected void Page_Load(object sender, EventArgs e)
{
string result = "callback({\"name\":\"zhangsan\",\"date\":\"2012-12-03\"})";
Response.Clear();
Response.Write(result);
Response.End();
}
2、jsonp跨域方案。
Jsonp的实现原理即是script标签跨域方式。
Jsonp跨域的服务端和script标签跨域是一样的,都要用callback(+data+)格式返回数据;
服务端代码:
protected void Page_Load(object sender, EventArgs e)
{
string callback = Request.QueryString["jsoncallback"];//从请求头中获取callback方法名
string result = callback + "({\"name\":\"zhangsan\",\"date\":\"2012-12-03\"})";
Response.Clear();
Response.Write(result);
Response.End();
}
客户端代码:
$.ajax({
async: false,
url: "http://192.168.0.5/Web/web1.aspx",
type: "GET",
dataType: 'jsonp',
//jsonp的值自定义,如果使用jsoncallback,那么服务器端,要返回一个jsoncallback的值对应的对象.
jsonp: 'jsoncallback',
//要传递的参数,没有传参时,也一定要写上
data: null,
timeout: 5000,
//返回Json类型
contentType: "application/json;utf-8",
//服务器段返回的对象包含name,data属性.
success: function (result) {
alert(result.date);
},
error: function (jqXHR, textStatus, errorThrown) {
alert(textStatus);
}
});
3、document.domain跨子域方案。
所谓跨子域,就是通过设置document.domain将两个不同域的资源放在同一个父域下面,然后两者就可以正常交互了。
A页面代码(http://www.example.com/a.html):
<html>
<head>
<script>
document.domain = "example.com";
function aa(){
alert("p");
}
</script>
</head>
<body>
<iframe src="http://example.com/b.html" id=”i”>
</iframe>
<script>
document.getElementById('i').onload = function(){
var d = document.getElementById('i').contentWindow;
d.a();
};
</script>
</body>
</html>
B页面代码(http://example.com/b.html):
<html>
<head>
<script>
document.domain = " example.com";
function a(){
alert("c");
}
</script>
</head>
<body>
</body>
</html>
注意:document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:www.org.example.com 中某个文档的document.domain 可以设成www.org.example.com、org.example.com 、example.com中的任意一个,但是不可以设成 ftp.www.org.example.com,因为这是当前域的子域,也不可以设成baidu.com,因为主域已经不相同了。
注意:document.domain的跨域必须是依托于一个html通过iframe的代理链接到另一个html,如果是ajax直接访问,这是行不通的。
主页面代码:
<!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';
//动态生成iframe载入a页面。
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>
B页面代码:
<script>
window.name = '需要跨域传递的数据';
</script>
4、window.name跨域方案。
Window的name属性存在于一个窗口的生命周期内,即使用window.location载入的界面都会共享这个name属性,且不会重置。
因此,可以我们可以通过这个name属性传递想要的数据。
主页面代码:
<!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';
//动态生成iframe载入a页面。
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){//判断是否为IE浏览器,因为IE支持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>
B页面代码:
<script>
window.name = '需要跨域传递的数据';
</script>
5、HTML5的window.postMessage跨域方案。
A页面代码:
<script>
function onLoad(){
var iframe=document.getElementById(‘iframe’);
var win=iframe.contentWindow;
win.postMessage(“你好”,*);//第一个参数为需要传递的消息,第二个为接收消息的域,可以为通配符。
}
</script>
B页面代码:
<script>
Window.onmessage=function(e){//注册事件接收消息;
e=e||event;//获取时间对象
alert(e.data);
}
</script>
6、cors跨域方案。
在服务器为response响应头添加跨域许可,可以使用通配符“*”。
(跨域请求可以是post方式或者get方式请求。)
服务端:
header("Access-Control-Allow-Origin:
http://www.a.com
");
客户端代码:
$.ajax("www.cros.com/api/data", {
type: "GET",
xhrFields: {
withCredentials: true
},
crossDomain: true,
success: function(data, status, xhr) {
}
});
本篇以摘抄、收集为主。
参考文档:
http://www.cnblogs.com/oneword/archive/2012/12/03/2799443.html
http://www.cnblogs.com/zjfree/archive/2011/02/24/1963591.html
http://narutolby.iteye.com/blog/1464436
http://www.cnblogs.com/2050/p/3191744.html