`
jiangzhenghua
  • 浏览: 592403 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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来对比一下:

  XmlHttpRequest Dynamic Script Tag
跨浏览器兼容 No Yes
跨域限制 Yes No
接收HTTP状态 Yes No (除了200)
支持Get、Post Yes No (GET only)
发送、接收HTTP头 Yes No
接收XML Yes Yes
接收JSON Yes Yes
支持同步、异步 Yes No (只能异步)

 

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

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

分享到:
评论
1 楼 make1828 2014-05-07  
 

相关推荐

    Javascript跨域访问解决方案

    Javascript跨域访问解决方案 个人在网上搜集的资料,用于传输信息,不提倡下载

    Javascript跨域和Ajax跨域解决方案

    NULL 博文链接:https://sun123start.iteye.com/blog/2150778

    前端常见跨域解决方案(全).mht

    分享转载:前端常见跨域解决方案 1、 通过jsonp跨域 2、 document.domain + iframe跨域 3、 location.hash + iframe 4、 window.name + iframe跨域 5、 postMessage跨域 6、 跨域资源共享(CORS) 7、 nginx...

    javascript跨域原因以及解决方案分享

    主要介绍了javascript跨域原因以及解决方案分享,十分的细致全面,有需要的小伙伴可以参考下。

    Javascript 跨域访问解决方案

    由于安全方面的考虑,Javascript被限制了跨域访问的能力,但是有时候我们希望能够做一些合理的跨域访问的事情,那么怎么办呢?

    WebApi 跨域问题解决方案:CORS

    同源策略:出于安全考虑,浏览器会限制脚本中发起的跨站请求,浏览器要求JavaScript或Cookie只能访问同域下的内容。 正是由于这个原因,我们不同项目之间的调用就会被浏览器阻止。比如我们最常见的场景:WebApi作为...

    JS跨域访问

    javascript 跨域访问 综合解决方案

    跨域问题的解决方案1

    跨域问题的解决方案1

    JS跨域解决方案之使用CORS实现跨域

     和大多数跨域的解决方案一样,JSONP也是我的选择,可是某天PM的需求变了,某功能需要改成支持POST,因为传输的数据量比较大,GET形式搞不定。所以折腾了下闻名已久的CORS(跨域资源共享,Cross-Origin Resource ...

    简单了解django处理跨域请求最佳解决方案

    为此,浏览器的鼻祖:网景(Netscape)公司提出了优秀的解决方案:著名的浏览器同源策略。现在所有支持JavaScript的浏览器都会使用这个策略。 同源:域名、协议、端口均相同的网站即为同源。 流程: 当一个浏览器的...

    关于JavaScript跨域问题及实时刷新解决方案

    在自己页面显示其他网站上面的数据,需要用Ajax,就涉及到跨域问题, 解决方案:jQuery.support.cors = true; (浏览器支持跨域访问), 实例: 代码如下: //浏览器支持跨域访问 jQuery.support.cors = true; $.ajax...

    WEB前端关于跨域问题的8种解决方案

    最近处理几个项目,设计服务器,所以研究了下跨域问题,综合总结了下,同行们多给点意见,其中涉及前端解决(最基本),JavaScript解决,socket解决,JSONP解决等,个人推荐使用socket和JSONP,使用方便,还稳定。

    Web应用跨域通信解决方案课件。

    讲到跨域通信,我们首先要了解什么是跨域?跨域大致的意思就是,比如:www.XXX.com域名下的js是不能操作www.YYY.com域名下的对象或者元素

    js原生跨域_用script标签的简单实现

    下面小编就为大家带来一篇js原生跨域_用script标签的简单实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    解决ajax不能访问本地文件问题(利用js跨域原理)

    本篇文章主要介绍了解决ajax不能访问本地文件问题(利用js跨域原理),具有一定的参考价值,有兴趣的可以了解一下。

    使用JavaScript 实现各种跨域的方法

     跨域——通过服务器端代理解决。 ②如今最优方案:使用JSON格式来传输数据,使用JSONP来跨域。 ③JSON:一种数据交换格式。基于纯文本、被原生JS支持。  格式:两种数据类型描述符:大括号{ }、方括号[ ]。分隔符...

    Ajax跨域的完美解决方案

    公司要做一个活动页面,在其过程... JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问; 实现方式  1) [removed] $.ajax({

    Ajax请求WebService跨域问题的解决方案

    3、解决方案: (1) JSONP:只支持GET方式 (2) CROS:跨域资源共享 以下为CROS解决方案:  a.在WebService接口加上响应头信息:  b.在web.config文件中加上相关配置节信息: 运用a或者b的解决方案后,浏览器头...

Global site tag (gtag.js) - Google Analytics