javascript跨域解决方案(一)

1、神马是跨域(Cross Domain)

说白点就是post、get的url不是你当前的网站,域名不同。例如在aaa.com/a.html里面,表单的提交action是bbb.com/b.html。

不仅如此,www.aaa.com和aaa.com之间也属于跨域,因为www.aaa.com是二级域名,aaa.com是根域名。

JavaScript出于安全方面的考虑,是不允许跨域调用其他页面的对象的(同源策略 Same-Origin Policy)。

关于JavaScript能否跨域通信的详细说明,见下表:

http://www.a.com/a.js访问以下URL的结果

URL说明是否允许通信
http://www.a.com/b.js同一域名下允许
http://www.a.com/script/b.js同一域名下不同文件夹允许
http://www.a.com:8000/b.js同一域名,不同端口不允许
https://www.a.com/b.js同一域名,不同协议不允许
http://70.32.92.74/b.js域名和域名对应ip不允许
http://script.a.com/b.js主域相同,子域不同不允许
http://a.com/b.js同一域名,不同二级域名(同上)不允许
http://www.b.com/b.js不同域名不允许

 

2、为嘛要跨域

跨域这东西其实很常见,例如我们可以把网站的一些脚本、图片或其他资源放到另外一个站点。例如我们可以使用Google提供的jQuery,加载时间少了,而且减少了服务器的流量,如下:

1
< script type = "text/java script" src = "https://aja x.googleapis.com/aj ax/libs/jquery/1.4.2/jquery.min.js" ></ script >

有时候不仅仅是一些脚本、图片这样的资源,我们也会希望从另外的站点调用一些数据(有时候是不得不这样),例如我希望获取一些blog的RSS来生成一些内容,再或者说我在“人人开放平台”上开发一个应用,需要调用人人的数据。

然而,很不幸的是,直接用XMLHttpRequest来Get或者Post是不行的,例如我用jQuery的$.get去访问本小博的主域名 :

1
2
3
4
{}, function (data){
alert( '跨域不是越狱:' +data)
}, "html" );

结果如下(总之就是不行啦~FF不报错,但是木有返回数据)

那咋么办捏?(弱弱的说,测试的时候我发现IE访问本地文件时,是可以跨域的,不过这也没啥用~囧~)

3、肿么跨域

下面为了更好的讲解和测试,我们可以通过修改hosts文件来模拟跨域的效果,hosts文件在C:\Windows\System32\drivers\etc 文件夹下。在下面加3行:

127.0.0.1 www.a.com

127.0.0.1 a.com

127.0.0.1 www.b.com

3.1、跨域代理

一种简单的办法,就是把跨域的工作交给服务器,从后台获取其他站点的数据再返回给前台,也就是跨域代理(Cross Domain Proxy)

这种方法似乎蛮简单的,改动也不太大。不过就是http请求多了些,响应慢了些,服务器的负载重了些~

 

3.2、document.domain+iframe

对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。

举www.a.com/a.html和a.com/b.html为例,只需在a.html中添加一个b.html的iframe,并且设置两个页面的document.domain都为'a.com'(只能为主域名),两个页面之间即可互相访问了,代码如下:

www.a.com/a.html中的script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
document.domain= 'a.com' ;
var ifr = document.createElement( 'iframe' );
ifr.src = 'http://a.com/b.html' ;
ifr.style.display = 'none' ;
document.body.appendChild(ifr);
ifr.onload = function (){
   //获取iframe的document对象
   //W3C的标准方法是iframe.contentDocument,
   //IE6、7可以使用document.frames[ID].document
   //为了更好兼容,可先获取iframe的window对象iframe.contentWindow
   var doc = ifr.contentDocument || ifr.contentWindow.document;
   // 在这里操纵b.html
   alert(doc.getElementById( "test" ).innerHTML);
};

 

a.com/b.html

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
< html >
< head >
< title ></ title >
< script type = "text/javascript" >
   document.domain='a.com';
</ script >
</ head >
< body >
< h1 id = "test" >Hello World</ h1 >
</ body >
</ html >

如果b.html要访问a.html,可在子窗口(iframe)中通过window.parent来访问父窗口的window对象,然后就可以为所欲为了(window对象都有了,还有啥不行的),同理子窗口也可以和子窗口之间通信。

于是,我们可以通过b.html的XMLHttpRequest来获取数据,再传给a.html,从而解决跨子域获取数据的问题。

但是这种方法只支持同一根域名下的页面,如果不同根域名(例如baidu.com想访问google.com)那就无能为力了。

 

3.3、动态script标签(Dynamic Script Tag)

这种方法也叫“动态脚本注入”。详情

这种技术克服了XMLHttpRequest的最大限制,也就是跨域请求数据。直接用JavaScript创建一个新的脚本标签,然后设置它的src属性为不同域的URL。

www.a.com/a.html中的script

1
2
3
4
5
var dynScript = document.createElement( 'script' );
dynScript.src = 'http://www.b.com/b.js' ;
dynScript.setAttribute( "type" , "text/javascript" );
document.getElementsByTagName( 'head' )[0]
     .appendChild(dynScript);

通过动态标签注入的必须是可执行的JavaScript代码,因此无论是你的数据格式是啥(xml、json等),都必须封装在一个回调函数中。一个回调函数如下:

www.a.com/a.html中的script

1
2
3
4
function dynCallback(data){
   //处理数据, 此处简单示意一下
   alert(data.content);
}

在这个例子中,www.b.com/b.js需要将数据封装在上面这个dynCallback函数中,如下:

1
dynCallback({content: 'Hello World' })

我们看到了让人开心的结果,Hello World~

 

不过动态脚本注入还是存在不少问题的,下面我们拿它和XMLHttpRequest来对比一下:

 XmlHttpRequestDynamic Script Tag
跨浏览器兼容NoYes
跨域限制YesNo
接收HTTP状态YesNo (除了200)
支持Get、PostYesNo (GET only)
发送、接收HTTP头YesNo
接收XMLYesYes
接收JSONYesYes
支持同步、异步YesNo (只能异步)

 

可以看出,动态脚本注入还是有不少限制,只能使用Get,不能像XHR一样判断Http状态等。

而且使用动态脚本注入的时候必须注意安全问题。因为JavaScript没有任何权限与访问控制的概念,通过动态脚本注入的代码可以完全控制整个页面,所以引入外部来源的代码必须多加小心。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值