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

javascript最全的10种跨域共享的方法

阅读更多

在客户端编程语言中,如javascript和ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义。同 源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和操作另外一个域的绝大部分属性和方法。那么什么叫相同域,什么叫不同的域呢?

 

本文永久链接地址: http://www.woiweb.net/10-cross-domain-methods.html

欢迎转载,转载请注明来源于我爱互联网,多谢合作!

同源策略

在客户端编程语言中,如javascript和 ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义。同源策略规定跨域之间的脚本是隔离的,一个域的脚 本不能访问和操作另外一个域的绝大部分属性和方法。那么什么叫相同域,什么叫不同的域呢?当两个域具有相同的协议(如http), 相同的端口(如80),相同的host(如www.example.org),那么我们就可以认为它们是相同的域。比如 http://www.example.org/index.html和http://www.example.org/sub/index.html是 同域,而http://www.example.org, https://www.example.org, http://www.example.org:8080, http://sub.example.org中的任何两个都将构成跨域。同源策略还应该对一些特殊情况做处理,比如限制file协议下脚本的访问权限。 本地的HTML文件在浏览器中是通过file协议打开的,如果脚本能通过file协议访问到硬盘上其它任意文件,就会出现安全隐患,目前IE8还有这样的 隐患。

受到同源策略的影响,跨域资源共享就会受到制约。但是随着人们的实践和浏览器的进步,目前在跨域请求的技巧上,有很多宝贵经验的沉淀和积累。这里我把跨域资源共享分成两种,一种是单向的数据请求,还有一种是双向的消息通信。接下来我将罗列出常见的一些跨域方式,以下跨域实例的源代码可以从这里获得

单向跨域

JSONP

JSONP (JSON with Padding)是一个简单高效的跨域方式,HTML中的script标签可以加载并执行其他域的javascript,于是我们可以通过script标记来动态加载其他域的资源。 例如我要从域A的页面pageA加载域B的数据,那么在域B的页面pageB中我以JavaScript的形式声明pageA需要的数据,然后在 pageA中用script标签把pageB加载进来,那么pageB中的脚本就会得以执行。JSONP在此基础上加入了回调函数,pageB加载完之后 会执行pageA中定义的函数,所需要的数据会以参数的形式传递给该函数。JSONP易于实现,但是也会存在一些安全隐患,如果第三方的脚本随意地执行, 那么它就可以篡改页面内容,截获敏感数据。但是在受信任的双方传递数据,JSONP是非常合适的选择。

flash URLLoader

flash有自己的一套安全策略,服务器可以通过crossdomain.xml文件来声明能被哪些域的SWF文件访问,SWF也可以通过API来确定自身能被哪些域的SWF加载。当跨域访问资源时,例如从域www.a.com请求域www.b.com上的数据,我们可以借助flash来 发送HTTP请求。首先,修改域www.b.com上的crossdomain.xml(一般存放在根目录,如果没有需要手动创建) ,把www.a.com加入到白名单。其次,通过Flash URLLoader发送HTTP请求,最后,通过Flash API把响应结果传递给JavaScript。Flash URLLoader是一种很普遍的跨域解决方案,不过需要支持iOS的话,这个方案就无能为力了。

Access Control

Access Control是比较超越的跨域方式,目前只在很少的浏览器中得以支持,这些浏览器可以发送一个跨域的HTTP请求(Firefox, Google Chrome等通过XMLHTTPRequest实现,IE8下通过XDomainRequest实现),请求的响应必须包含一个Access- Control-Allow-Origin的HTTP响应头,该响应头声明了请求域的可访问权限。例如www.a.com对www.b.com下的 asset.php发送了一个跨域的HTTP请求,那么asset.php必须加入如下的响应头:

header("Access-Control-Allow-Origin: http://www.a.com");

window.name

window 对象的name属性是一个很特别的属性,当该window的location变化,然后重新加载,它的name属性可以依然保持不变。那么我们可以在页面 A中用iframe加载其他域的页面B,而页面B中用JavaScript把需要传递的数据赋值给window.name,iframe加载完成之后,页 面A修改iframe的地址,将其变成同域的一个地址,然后就可以读出window.name的值了。这个方式非常适合单向的数据请求,而且协议简单、安 全。不会像JSONP那样不做限制地执行外部脚本。

server proxy

在数据提供方没有提供对JSONP协议或者 window.name协议的支持,也没有对其它域开放访问权限时,我们可以通过server proxy的方式来抓取数据。例如当www.a.com域下的页面需要请求www.b.com下的资源文件asset.txt时,直接发送一个指向 www.b.com/asset.txt的Ajax请求肯定是会被浏览器阻止。这时,我们在www.a.com下配一个代理,然后把Ajax请求绑定到这个代理路径下,例如www.a.com/proxy/, 然后这个代理发送HTTP请求访问www.b.com下的asset.txt,跨域的HTTP请求是在服务器端进行的,客户端并没有产生跨域的Ajax请求。这个跨域方式不需要和目标资源签订协议,带有侵略性,另外需要注意的是实践中应该对这个代理实施一定程度的保护,比如限制他人使用或者使用频率。

双向跨域

document.domain

通 过修改document的domain属性,我们可以在域和子域或者不同的子域之间通信。同域策略认为域和子域隶属于不同的域,比如www.a.com和 sub.a.com是不同的域,这时,我们无法在www.a.com下的页面中调用sub.a.com中定义的JavaScript方法。但是当我们把它 们document的domain属性都修改为a.com,浏览器就会认为它们处于同一个域下,那么我们就可以互相调用对方的method来通信了。

FIM – Fragment Identitier Messaging

不 同的域之间,JavaScript只能做很有限的访问和操作,其实我们利用这些有限的访问权限就可以达到跨域通信的目的了。FIM (Fragment Identitier Messaging)就是在这个大前提下被发明的。父窗口可以对iframe进行URL读写,iframe也可以读写父窗口的URL,URL有一部分被称 为frag,就是#号及其后面的字符,它一般用于浏览器锚点定位,Server端并不关心这部分,应该说HTTP请求过程中不会携带frag,所以这部分 的修改不会产生HTTP请求,但是会产生浏览器历史记录。FIM的原理就是改变URL的frag部分来进行双向通信。每个window通过改变其他 window的location来发送消息,并通过监听自己的URL的变化来接收消息。这个方式的通信会造成一些不必要的浏览器历史记录,而且有些浏览器 不支持onhashchange事件,需要轮询来获知URL的改变,最后,URL在浏览器下有长度限制,这个制约了每次传送的数据量。

Flash LocalConnection

页 面上的双向通信也可以通过Flash来解决,Flash API中有LocalConnection这个类,该类允许两个SWF之间通过进程通信,这时SWF可以播放在独立的Flash Player或者AIR中,也可以嵌在HTML页面或者是PDF中。遵循这个通信原则,我们可以在不同域的HTML页面各自嵌套一个SWF来达到相互传递 数据的目的了。SWF通过LocalConnection交换数据是很快的,但是每次的数据量有40kb的大小限制。用这种方式来跨域通信过于复杂,而且 需要了2个SWF文件,实用性不强。

window.postMessage

window.postMessage是HTML5定义的一个很新的方法,这个方法可以很方便地跨window通信。由于它是一个很新的方法,所以在很旧和比较旧的浏览器中都无法使用。

Cross Frame

Cross Frame是FIM的一个变种,它借助了一个空白的iframe,不会产生多余的浏览器历史记录,也不需要轮询URL的改变,在可用性和性能上都做了很大 的改观。它的基本原理大致是这样的,假设在域www.a.com上有页面A.html和一个空白代理页面proxyA.html, 另一个域www.b.com上有个页面B.html和一个空白代理页面proxyB.html,A.html需要向B.html中发送消息时,页面会创建 一个隐藏的iframe, iframe的src指向proxyB.html并把message作为URL frag,由于B.html和proxyB.html是同域,所以在iframe加载完成之后,B.html可以获得iframe的URL,然后解析出 message,并移除该iframe。当B.html需要向A.html发送消息时,原理一样。Cross Frame是很好的双向通信方式,而且安全高效,但是它在Opera中无法使用,不过在Opera下面我们可以使用更简单的 window.postMessage来代替。

总结

跨域的方法很多,不同的应用场景我们都可以找到一个最合适的解决方 案。比如单向的数据请求,我们应该优先选择JSONP或者window.name,双向通信我们采取Cross Frame,在未与数据提供方没有达成通信协议的情况下我们也可以用server proxy的方式来抓取数据。

分享到:
评论
23 楼 liltos 2011-03-28  
我用的是这个
FIM – Fragment Identitier Messaging
#号后面的应该是叫 hash
两边都用轮询的方式获取数据
URL的长度限制基本只需要应对IE就可
22 楼 dontal 2011-03-28  
楼主能否指点一下,如果ajax访问跨域资源,使用jsonp方式,那么是否还需要使用xmlHttpRequest对象,我的理解:在head中增加<script>标签实际上是由页面帮我们去调用另一个域上的逻辑,那么是否还有必要通过xmlHttpRequest去请求?
另一个问题,ajax默认是异步传输,那么使用<script>标签的方式是同步的还是异步的,页面是不是要加载完<script>后再会执行后面的语句?
21 楼 dengjianqiang200 2011-03-23  
zhaoxy_sunrain 写道
我在项目中用过P3P协议,也可以实现跨域访问。

response.setHeader("P3P","CP=\"NON DSP COR CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa CONa HISa TELa OTPa OUR UNRa IND UNI COM NAV INT DEM CNT PRE LOC\"");



最终是用cookie吗?

20 楼 dengjianqiang200 2011-03-23  
whiletrue 写道
我们的一个方案,使用post的方式来跨域提交,把参数序列化从A传递至B,B得到后再反序列化即可.模拟了对话框模式,也不错.


那得AB间相互信任才行,而且如何判断从B返回的数据是A想要的?
19 楼 dengjianqiang200 2011-03-23  
achun 写道
document.domain
学习了,以前还真不知道这个方法

这个只适用于子域间或子域同父域之间,其他域是不行的。
18 楼 dengjianqiang200 2011-03-23  
achun 写道
document.domain
学习了,以前还真不知道这个方法


这只适用于子域与子域或子域与父域之间的通信,其他的域是不行的。
17 楼 dengjianqiang200 2011-03-23  
rashrash 写道
还是使用jsonp简单方便

jsonp只能实现单向请示,而且不支持post
16 楼 achun 2011-02-01  
document.domain
学习了,以前还真不知道这个方法
15 楼 rashrash 2011-02-01  
还是使用jsonp简单方便
14 楼 whiletrue 2011-01-30  
我们的一个方案,使用post的方式来跨域提交,把参数序列化从A传递至B,B得到后再反序列化即可.模拟了对话框模式,也不错.
13 楼 zhaoxy_sunrain 2011-01-29  
我在项目中用过P3P协议,也可以实现跨域访问。

response.setHeader("P3P","CP=\"NON DSP COR CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa CONa HISa TELa OTPa OUR UNRa IND UNI COM NAV INT DEM CNT PRE LOC\"");
12 楼 dir_murong 2011-01-28  
就知道jsonp
11 楼 LoriSun 2011-01-28  
document.domain 是一个方便的方式。 推荐
10 楼 netbuddy 2011-01-28  
<div class="quote_title">dengjianqiang200 写道</div>
<div class="quote_div">    就是说通过A域中创建一个隐藏iframe,并将其src改为:<a href="http://www.b.com/proxyB.html">www.b.com/proxyB.html</a> + "#" + 你要传递的参数和值(message=***&amp;domain=***),同时需要在代理页面中增加监听事件,将“#”后的参数进行处理封闭后,进行事件广播,将消息传递给同域下的B.html,反过来一样。<br>
</div>
<p> </p>
<p>    明白了,受教了!</p>
9 楼 goldduck 2011-01-27  
灰常经典,赞一个。
在做页面集成的时候使用一些技巧,可以得到良好的用户体验。
8 楼 dengjianqiang200 2011-01-27  
<div class="quote_title">mlw2000 写道</div>
<div class="quote_div">
<div class="quote_title">lwyx2000 写道</div>
<div class="quote_div">
<div class="quote_title">jfzlnyf 写道</div>
<div class="quote_div">
<div class="quote_title">mlw2000 写道</div>
<div class="quote_div">
<div class="quote_title">引用</div>
<div class="quote_div">Cross Frame<br>它的基本原理大致是这样的,假设在域www.a.com上有页面A.html和一个空白代理页面proxyA.html, 另一个域www.b.com上有个页面B.html和一个空白代理页面proxyB.html;<br><br>A.html需要向B.html中发送消息时,页面会创建一个隐藏的iframe, iframe的src指向proxyB.html并把message作为URL frag,由于B.html和proxyB.html是同域,所以在iframe加载完成之后,B.html可以获得iframe的URL,然后解析出 message,并移除该iframe。<br>
</div>
<br>是不是我比较笨,还是没理解,如下:<br>A.html创建的iframe(src=proxyB.html?message=HelloWorld)是在A.html的页面中;<br>那么“在iframe加载完成之后,B.html可以获得iframe的URL”???<br>B.html是什么时候加载的,难道是“神马”?</div>
<br><br>我也想知道</div>
<br>~~有人给讲讲吗·~偶也不明白</div>
<br><br>没办法,还是自力更生,<br>见附件图片,可知Cross Frame仅仅在"B.html以iframe的形式嵌入在A.html"的情况。</div>
<p> </p>
<p> </p>
<p>就是说通过A域中创建一个隐藏iframe,并将其src改为:www.b.com/proxyB.html + "#" + 你要传递的参数和值(message=***&amp;domain=***),同时需要在代理页面中增加监听事件,将“#”后的参数进行处理封闭后,进行事件广播,将消息传递给同域下的B.html,反过来一样。</p>
<p>额,可能还是有些乱,上个代码给大家。大家可以补充指教,如果有跨域的更好的方法,希望大家贴上来啊。</p>
7 楼 mlw2000 2011-01-27  
lwyx2000 写道
jfzlnyf 写道
mlw2000 写道
引用
Cross Frame
它的基本原理大致是这样的,假设在域www.a.com上有页面A.html和一个空白代理页面proxyA.html, 另一个域www.b.com上有个页面B.html和一个空白代理页面proxyB.html;

A.html需要向B.html中发送消息时,页面会创建一个隐藏的iframe, iframe的src指向proxyB.html并把message作为URL frag,由于B.html和proxyB.html是同域,所以在iframe加载完成之后,B.html可以获得iframe的URL,然后解析出 message,并移除该iframe。

是不是我比较笨,还是没理解,如下:
A.html创建的iframe(src=proxyB.html?message=HelloWorld)是在A.html的页面中;
那么“在iframe加载完成之后,B.html可以获得iframe的URL”???
B.html是什么时候加载的,难道是“神马”?


我也想知道

~~有人给讲讲吗·~偶也不明白


没办法,还是自力更生,
见附件图片,可知Cross Frame仅仅在"B.html以iframe的形式嵌入在A.html"的情况。
6 楼 lwyx2000 2011-01-27  
jfzlnyf 写道
mlw2000 写道
引用
Cross Frame
它的基本原理大致是这样的,假设在域www.a.com上有页面A.html和一个空白代理页面proxyA.html, 另一个域www.b.com上有个页面B.html和一个空白代理页面proxyB.html;

A.html需要向B.html中发送消息时,页面会创建一个隐藏的iframe, iframe的src指向proxyB.html并把message作为URL frag,由于B.html和proxyB.html是同域,所以在iframe加载完成之后,B.html可以获得iframe的URL,然后解析出 message,并移除该iframe。

是不是我比较笨,还是没理解,如下:
A.html创建的iframe(src=proxyB.html?message=HelloWorld)是在A.html的页面中;
那么“在iframe加载完成之后,B.html可以获得iframe的URL”???
B.html是什么时候加载的,难道是“神马”?


我也想知道

~~有人给讲讲吗·~偶也不明白
5 楼 honlin 2011-01-27  
研究的比较全面,有深度。
4 楼 jfzlnyf 2011-01-27  
mlw2000 写道
引用
Cross Frame
它的基本原理大致是这样的,假设在域www.a.com上有页面A.html和一个空白代理页面proxyA.html, 另一个域www.b.com上有个页面B.html和一个空白代理页面proxyB.html;

A.html需要向B.html中发送消息时,页面会创建一个隐藏的iframe, iframe的src指向proxyB.html并把message作为URL frag,由于B.html和proxyB.html是同域,所以在iframe加载完成之后,B.html可以获得iframe的URL,然后解析出 message,并移除该iframe。

是不是我比较笨,还是没理解,如下:
A.html创建的iframe(src=proxyB.html?message=HelloWorld)是在A.html的页面中;
那么“在iframe加载完成之后,B.html可以获得iframe的URL”???
B.html是什么时候加载的,难道是“神马”?


我也想知道

相关推荐

    主题:javascript最全的10种跨域共享的方法.docx

    【标题】:JavaScript中最全面的10种跨域共享技术详解 在JavaScript和其他客户端编程语言中,同源策略是保障网络安全的重要机制。它规定,来自不同源(协议、域名或端口不同)的脚本之间不能互相访问对方的大部分...

    (转)10种方式实现跨域资源的共享

    标题"10种方式实现跨域资源的共享"暗示了我们将探讨多种克服同源策略限制的方法。以下是一些主要的跨域资源共享实现方式: 1. **JSONP(JSON with Padding)**: JSONP是一种较早的跨域方法,通过动态插入`&lt;script&gt;`...

    跨域共享session (实现http跳转https 共享session)

    但是,为了提供更好的用户体验,特别是在单点登录(Single Sign-On, SSO)场景下,跨域共享session变得非常重要。 **一、跨域共享session原理** 1. **JSONP(JSON with Padding)**:JSONP是一种早期的跨域解决方案...

    javascript插件 解决双向跨域问题

    jcrossdomain是一个专门用于解决JavaScript跨域问题的工具,尤其适用于需要双向通信的场景。它通过创建隐藏的IFrame和利用window.postMessage API来实现跨域通信。window.postMessage是HTML5引入的一个API,允许来自...

    javascript跨域方案总结

    JavaScript跨域方案是Web开发中的一个重要主题,尤其是在构建现代Web应用程序时。由于浏览器的安全策略,JavaScript在不同域名之间默认不允许进行通信,这就是所谓的“同源策略”。然而,开发者经常需要在多个域之间...

    arcgis api for javascript跨域处理方案

    在使用ArcGIS API for JavaScript开发Web应用程序时,经常会遇到跨域问题。这是因为浏览器的安全策略限制了JavaScript从一个源(域名、协议或端口)请求另一个源的数据。ArcGIS API for JavaScript是一个强大的工具...

    javascript/jquery 跨域访问

    JavaScript 和 jQuery 是Web开发中广泛使用的两种技术,它们在实现跨域访问方面起着关键作用。跨域访问是Web应用程序中常见的需求,特别是在Ajax请求、API调用或数据共享时。由于浏览器的安全策略,不同域名、协议或...

    javascript跨域访问的方法.pdf

    以下是两种主要的JavaScript跨域技术:基于iframe的跨域和JSONP(JSON with Padding)。 1. 基于iframe实现跨域: 当两个页面的基础域相同,如aa.xx.com和bb.xx.com,可以通过设置`document.domain`来实现跨子域的...

    javascript跨域的方法汇总.docx

    JavaScript跨域是Web开发中一个常见的挑战,主要是由于浏览器的安全策略——同源策略(Same-origin policy)限制。同源策略要求网页只能访问与其自身URL协议、域名和端口完全相同的资源,以防止恶意脚本窃取数据。...

    Javascript跨域访问解决方案

    总结来说,JavaScript跨域访问有多种解决方案,开发者应根据具体需求和环境选择合适的方法。JSONP适合简单的GET请求,CORS更通用且安全,代理服务器适用于服务器无跨域控制能力的情况,WebSocket则适用于需要实时...

    iframe 跨域解决方法

    解决`iframe`跨域问题有多种方法: 1. **使用`CORS`(跨源资源共享)**:服务器可以通过设置响应头`Access-Control-Allow-Origin`来允许特定的源访问其资源。例如,`Access-Control-Allow-Origin: *`表示允许所有源...

    解决跨域的几种方法.zip

    每种方法都有其适用场景和优缺点,开发者需要根据实际需求选择合适的跨域解决方案。例如,CORS和JSONP适合大部分情况,但CORS需要服务器配合,而JSONP仅限GET请求;IFrame适合处理跨域的嵌入内容;postMessage适用于...

    JavaScript跨域总结

    JavaScript跨域总结 在Web开发中,由于浏览器的同源策略限制,JavaScript代码通常只能访问与自身页面协议、域名和端口完全相同的资源。这种安全机制是为了防止恶意脚本通过跨站点请求获取用户敏感信息。然而,随着...

    CORS跨域资源共享及解决方案.docx

    ### CORS跨域资源共享及其解决方案详解 #### 一、CORS跨域资源共享背景 在现代Web应用开发中,前后端分离已成为一种主流趋势。在这种模式下,前端负责展示...开发者可以根据实际情况选择最合适的方法来解决跨域问题。

    什么是跨域?跨域解决方法.docx

    4. CORS(Cross-Origin Resource Sharing),是跨域资源共享的缩写,是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。 六、设置 document.domain 解决无法读取非同源网页的 Cookie 问题 可以通过设置相同的 ...

    iframe 跨域访问session

    6. **服务器端代理**:最安全且可靠的方法是不在客户端处理跨域`session`,而是通过服务器端的代理。例如,服务器可以接收来自`iframe`的请求,然后转发到实际的目标,并在响应中包含`session`信息。 在提供的文件...

    JAVA前后台跨域的两种方法(详细步骤)

    在现代Web开发中,跨域资源共享(CORS)是一个常见的需求,特别是在使用JavaScript进行前后端分离的架构下。本文将详细介绍两种在JAVA后台处理跨域问题的方法,以便于前端和后端之间的数据交互。 方法一:CORS ...

    跨域引用资源技术

    跨域引用资源技术是Web开发中的一个重要概念,它涉及到浏览器的同源策略和资源的共享。同源策略是由浏览器强制实施的一种安全策略,确保JavaScript只能访问与当前页面同源(即相同协议、相同域名和相同端口)的网页...

Global site tag (gtag.js) - Google Analytics