ajax跨域和JS的跨域通信(Cross The Site)的几种解决
方案
最近做的一个项目中需要ajax跨域取得数据,如果是在本域中确实没有问题,但是放到二级域和其他域下浏览器直接就弹出提示框:“该页正在访问其控制范围之外的数据,这有些危险,是否继续" 1.什么引起了ajax跨域不能的问题 ajax本身实际上是通过XMLHttpRequest对象来进行数据的交互,而浏览器出于安全考虑,不允许js代码进行跨域操作,所以会警告。 2.有什么完美的解决方案么? 没有。解决方案有不少,但是只能是根据自己的实际情况来选择。 具体情况有: 一、本域和子域的相互访问: www.aa.com和book.aa.com 二、本域和其他域的相互访问: www.aa.com和www.bb.com 用 iframe 三、本域和其他域的相互访问: www.aa.com和www.bb.com 用 XMLHttpRequest访问代理 四、本域和其他域的相互访问: www.aa.com和www.bb.com 用 JS创建动态脚本 解决 方法: 一、如果想做到数据的交互,那么www.aa.com和book.aa.com必须由你来开发才可以。可以将book.aa.com用iframe添加到 www.aa.com的某个页面下,在www.aa.com和iframe里面都加上document.domain = "aa.com",这样就可以统一域了,可以实现跨域访问。就和平时同一个域中镶嵌iframe一样,直接调用里面的JS就可以了。(这个办法我没有尝试,不过理论可行) 二、当两个域不同时,如果想相互调用,那么同样需要两个域都是由你来开发才可以。用iframe可以实现数据的互相调用。解决方案就是用window.location对象的hash属性。hash属性就是 http://domian/web/a.htm#dshakjdhsjka 里面的#dshakjdhsjka。利用JS改变hash值网页不会刷新,可以这样实现通过JS访问hash值来做到通信。不过除了IE之外其他大部分浏览器只要改变hash就会记录历史,你在前进和后退时就需要处理,非常麻烦。不过再做简单的处理时还是可以用的,具体的 代码我再下面有下载。大体的过程是页面a和页面b在不同域下,b通过iframe添加到a里,a通过JS修改iframe的hash值,b里面做一个监听(因为JS只能修改hash,数据是否改变只能由b自己来判断),检测到b的hash值被修改了,得到修改的值,经过处理返回a需要的值,再来修改a的hash值(这个地方要注意,如果a 本身是那种查询页面的话比如 http://domian/web/a.aspx?id=3,在b中直接parent.window.location是无法取得数据的,同样报没有权限的错误,需要a把这个传过来,所以也比较麻烦),同样a里面也要做监听,如果hash变化的话就取得返回的数据,再做相应的处理。 三、这种情形是最经常遇到的,也是用的最多的了。就是www.aa.com和www.bb.com你只能修改一个,也就是另外一个是别人的,人家告诉你你要取得数据就访问某某连接参数是什么样子的,最后返回数据是什么格式的。而你需要做的就是在你的域下新建一个网页,让服务器去别人的 网站上取得数据,再返回给你。domain1下的a向同域下的GetData.aspx请求数据,GetData.aspx向domain2下的 ResponseData.aspx发送请求,ResponseData.aspx返回数据给GetData.aspx, GetData.aspx再返回给a,这样就完成了一次数据请求。GetData.aspx在其中充当了代理的作用。具体可以看下我的代码。 四、这个和上个的区别就是请求是使用<script>标签来请求的,这个要求也是两个域都是由你来开发才行。原理就是JS文件注入,在本域内的a 内生成一个JS标签,它的SRC指向请求的另外一个域的某个页面b,b返回数据即可,可以直接返回JS的代码。因为script的src属性是可以跨域的。具体看代码,这个也比较简单。 code: http://www.live-share.com/files/300697/Cross_The_Site_Test_code.rar.html (csdn不能粘贴附件么?) 总结: 第一种情况:域和子域的问题,可以完全解决交互。 第二种情况:跨域,实现过程非常麻烦,需要两个域开发者都能控制,适用于简单交互。 第三种情况:跨域,开发者只控制一个域即可,实现过程需要增加代理取得数据,是常用的方式。 第四种情况:跨域,两个域开发者都需要控制,返回一段js代码。 PS:代码自己按照情况修改即可。 这是拿别人的参考链接,老美的文章比较多。 1. Security Considerations: Dynamic HTML http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/sec_dhtml.asp 2. About Cross-Frame Scripting and Security http://msdn.microsoft.com/library/default.asp?url=/workshop/author/om/xframe_scripting_security.asp 3. Cross-Domain Proxy http://ajaxpatterns.org/Cross-Domain_Proxy 4. Cross Domain XMLHttpRequest using an IFrame Proxy http://manual.dojotoolkit.org/WikiHome/DojoDotBook/Book75 5. Back Button Support for Atlas UpdatePanels http://www.nikhilk.net/BackButtonSupport.aspx 6. Cross-document messaging hack http://blog.monstuff.com/archives/000304.html 7. Building Mash-ups with "Atlas" http://atlas.asp.net/docs/Walkthroughs/DevScenarios/bridge.aspx 8. Calling web services hosted outside of your application with “Atlas” http://blogs.msdn.com/federaldev/archive/2006/07/31/684229.aspx http://www.federaldeveloper.com/Shared%20Documents/Presentations%20by%20Marc% 20Schweigert/CallAtlasWebServiceInDifferentProject.zip 9. AJAX Tip: Passing Messages Between iframes http://www.25hoursaday.com/weblog/PermaLink.aspx?guid=3b03cf9d-b589-4838-806e-64efcc0a1a15 10. OSCON Cross-site Ajax Slides http://blog.plaxo.com/archives/2006/07/oscon_crosssite.html http://www.plaxo.com/css/api/Joseph-Smarr-Plaxo-OSCON-2006.ppt 11. OSCON 2006: Cross-site Ajax http://www.sitepoint.com/blogs/2006/07/28/oscon-2006-cross-site-ajax/
-------------------------------------------------------------------------------------------
Javascript 跨域访问解决方案
2008-9-27 15:03:00
查看学习心得
由于安全方面的考虑,Javascript被限制了跨域访问的能力,但是有时候我们希望能够做一些合理的跨域访问的事情,那么怎么办呢? 这里分两类情况: 一、基于同一父域的子域之间页面的访问 参见如下3个domain域: 1、taobao.com 它们有相同的父域 taobao.com 二、基于不同父域页面之间的访问 参见如下3个domain域: 1、taobao.com 3、sina.com.cn 它们具有不同的父域。 解决它们之间跨域的方案: <!--[if !supportLists]-->① <!--[endif]-->服务器Proxy: 域A的页面JS需要访问域B下的链接获取数据,该方案在域A的服务器端建立一个Proxy程序(可能是ASP、servlet等任何服务端程序),域A的页面JS直接调用本域下的Proxy程序,proxy程序负责将请求发送给域B下的链接并获取到数据,最后再通过Proxy将数据返回给页面JS使用。 经过的访问流程就是: 域A下JS--à域A 下Proxy---à域B下的链接 例子: 第一步: 域A: http://Jipiao.taobao.com/test.htm 页面上javascript脚本 <script type=”text/javascript”> 第二步: Proxy程序(这里假定是一个servlet): Public class Proxy extends …….{ 注意:这种方案要求域B返回的数据必须是合法的JSON格式或者如JS文件的格式。 域B返回的数据格式如下: Var remote={test:’hello’}; 对于基于同一父域的子域之间页面的访问这一类情况,还有第三种方式 <html> 这里 promotion.taobao.com/xxxx.htm 页面也需要设置document.domain="taobao.com", 这种方法才能奏效。之所以这种iframe的方法不适合不同父域之间的跨域,是因为设置document.domain只能设置为自己的父域,而不是能设置为其他域,例如:jiapiao.taobao.com只能设置document.domain=”taobao.com” ,而不是是document.domain=”baidu.com” 优缺点比较: 这里列举的三种方案各有优缺点: Proxy方案优点是可以适用用于几乎所有的跨域访问,而且只需要要一个域中进行开发,另一个域可以提供任何类型格式的数据。缺点是这种方案经过了中间Proxy,所以延迟可能稍微大一点,并且会加重本域服务器的负荷,开发工作量也稍微大一点。 Script标签的方案可以说是非常简单的,不用几行代码就搞定了事,不过它对返回的数据格式要求有点严格,只能是Json格式数据,如果是其他格式的数据,那么这种方法就无能为力了。
跨域登录(一)跨域登录是一个比较烦人的事情,往往我们需要写文章记录下来,或者探讨,或者抛砖引玉的问题,都是令人头疼的。上次简单得写了一篇关于跨域登录的文章,只讲了大体的实现过程。但是现在碰到了更大的问题,这篇文章将会介绍这个成败,并探讨、实现新方案的可行性。 跨域登录需要一张通行证,也可以称之为票据。就老衲现在知道和实验的方式一共有三种: 1、浏览器get参数; 每个都有特定的条件,以及需要处理的细节,也会带来一些新问题。根据经验,浏览器带参数,将会使系统开发得不像个东西,至少我是这么认为的。需要考虑对这个地址参数处理的各种策略,一开始我就否定了这个方案。在我需要改造的项目中有4个独立域名,跳转来跳转去,将会给用户造成极为不爽的体验。 session也可以解决问题,但是有一个问题无法解决。 先看看怎么用session解决问题。假设现在有a.com,b.com,现在开两个子域名: passport.a.com和passport.b.com。然后把这两个域名指向同一个站点,也就是在同一个站点的http投绑定这两个域名。 那么登录的时候,在 passport.a.com上登录成功,就可以设置一个session,那么在两个系统当中都是可以通过代理文件,访问到这个session的,这个方案确实是可行的。但是session只能保持20分钟,新问题就出来了。假设这个用户20分钟没有去操作,而打开了另外一个域名,那么这个判断就失效了。访问本域是没问题的,cookie还在那里摆着。 我比较倾向于用cookie来解决问题。上一次设计的系统,可以说极其简单。4个系统,有3个是asp.net的,还有个论坛是asp的(不用说就是动网的了)。现在就有四套登录系统。如果整体上全部改造,老衲认为成本太大了。后来四处逛网站,借鉴了Sohu的登录方式,但是只做了个体验的实现,如果全部实现了就不会现在在这里探讨这个问题了。解决方案就是javascript + iframe实现的。 本来想用纯javascript实现,然后给src的文件带参数,但是实际开发过程中,应该是我的js水平太菜,所以感觉不到想要的那种效果。后来就采用了javascript + iframe的方式来实现。是无刷新的那种哦,呵呵。 // JavaScript Document
javascript使用很简单,点击登录也就是调用了OnSign方法,将会向passport.c.com/jslogin.aspx发出请求。
Response.AddHeader("P3P", @"CP=""CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR""");
jslogin的代码就是个验证的过程,加的P3P头,是可以跨域写入Cookie的保证。这里使用的是.Net 的Forms验证,要保持和其它域名加密方式以及名称的统一。假如有两个域同时指向一个站点的话。
这里返回javascript并且操作iframe的父窗口,改变地址,而引用的js会监视地址栏,发现数据,根据数据的格式,判断是否验证成功,如果成功了,那么会向各个站点下的一个SetLogin文件发出请求,当然被请求的页面需有P3P头。
这样在一个地方登录,实际上是同时向其它域名写入Cookie,退出的原理也是一样的。
但是,在Maxthon中Iframe操作父窗口地址这个操作是不允许的,它认为这个不安全,我倒是没觉得。这个问题还不太大,毕竟有Maxthon的用户不是太多,即使用了,告诉他不能用,他也会用IE。
但是IE8 beat 2这种操作方式将会弹出新窗口。在IE8 beat2中使用Iframe解决方案就会变得体验很不好。而且还给老衲带来了心灵上的伤害,以后不敢什么都写在客户端了,浏览器版本一变,对整体影响太大了。
下一个可替代方案就是使用反向代理,sohu的无刷新登录就是基于这个实现的据说,目前还在研究中。上一次因为时间急迫,没有时间仔细实验。这次是没办法躲过去了。
|
Javascript跨域和Ajax跨域解决方案
最新推荐文章于 2024-09-16 08:47:17 发布