`

Javascript跨域和Ajax跨域解决方案总结(转)

阅读更多

最近做的一个项目中需要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属性是可以跨域 的。具体看代码,这个也比较简单。



总结:
第一种情况:域和子域的问题,可以完全解决交互。
第二种情况:跨域,实现过程非常麻烦,需要两个域开发者都能控制,适用于简单交互。
第三种情况:跨域,开发者只控制一个域即可,实现过程需要增加代理取得数据,是常用的方式。
第四种情况:跨域,两个域开发者都需要控制,返回一段js代码。


===================

A域有页面a.html,其中有iframe包含B域的页面b.html,现在要通过a.html上的一个按钮,来把a.html页面上一个文本框的值传递到b.html页面的文本框。

注: 这里b.html是html网页,不能接收其他网站post过来的值,所以不能用直接post的方法来传值,但是,如果接收页面是b.aspx或者 b.asp 呢,那不是可以直接post了么?答案是肯定的,确实可以,但是b.asp或b.aspx必须要刷新,才可以,如何能不刷新的动态改变接收页的元素或者值 呢?(IE的本地项目是可以实现跨域访问的,但是外网的跨域访问默认是被拒绝的。FireFox本地项目以及外网的跨域访问都是被拒绝的。)

原理:

浏览器禁止跨域数据访问,但是浏览器并没有禁止跨域跨框架的post传值。我们可以在A域,post到B域的某个页面的框架中,然后通过B域的框架页来实现本域内的数据访问。这其实是html应用中的一个小技巧,并没有用到其他高深的知识就实现了跨域的数据提交。

方法:

在B域中添加两个页面,来实现跨域的数据访问,post.aspx和main.aspx。

页面关系如下,A域的a.html包含一个框架,框架页地址是B域的main.aspx,main.aspx是一个框架集包含两个框架,(frmMain)b.html 和(frmPost)post.aspx.

A域的a.html:

<form action="http://www.b**.com/post.aspx" method="post" target="frmPost">

<input id="cmd" type="text" size="20">

<input type="submit">

</form>

<iframe src="http://www.b**.com/main.aspx"></iframe>

B域的main.aspx:

<frameset rows="*,0" frameborder="no" border="0" framespacing="0">

<frame src="b.html" name="frmMain">

<frame src="post.aspx" name="frmPost">

</frameset>

 

我们先把要传递到B域的数据保存到a.html的form中,然后post到B域的post.aspx.

这时post.aspx接收到值,然后执行本域内的父框架访问b.html。

string cmd = Request.Form["cmd"];

if (null != cmd && string.Empty != cmd)

{

        Response.Write("<script language=/"JavaScript/" for=/"window/" event=/"onload/"> if (parent && parent.frames[/"frmMain/"]) { 这里添加控制b.html的执行代码} </script> ");

}

不难发现,这里利用跳跃跨frame(即中间跃过了一层frame)的方法,来实现跨域的数据访问。即post到frame的子frame里面。

后记:

这个例子不过是一些特殊的情况下跨域访问的解决方案,也许对你会有所帮助。因为方法简单,应用也就有很多局限性。(不过偶倒是觉得这样很象ajax哦,页面没有刷新,同样完成了一次服务端的数据处理^o^)。

相关网文资料:

web应用的跨域访问解决方案

做过跨越多个网站的Ajax开发的朋友都知道,如果在A网站中,我们希望使用Ajax来获得B网站中的特定内容,如果A网站与B网站不在同一个域中,那么就出现了跨域访问问题。Ajax的跨域访问问题是现有的Ajax开发人员比较常遇到的问题。

IE对于跨域访问的处理是,弹出警告框,提醒用户。如果用户将该网站纳入可信任网站,或者调低安全级别,那么这个问题IE就不会在提醒你。

FireFox等其它非微软的浏览器遇到跨域访问,则解决方案统一是拒绝访问。

有 人说,IE是主流浏览器,只要它能正常使用就好了。此言差已,IE虽然能够处理,但是是有前提的,要么用户不厌其烦地在页面弹出警告框之后点击是(点击否 就不执行该Ajax调用了),要么用户将该网站纳入可信任站点。这两种做法,在企业管理系统的应用中倒是比较常见,因为系统管理员可以以行政手段保证用户 的行为。但是对于互联网上的网站或者门户开发,这种做法则不行。

最近遇到了这个问题,需要在跨域访问结束之后完成使主窗口出现一些特效,搜索了一些资料,通过不断尝试以及在不同浏览器中进行兼容性测试,找到了几个可行的方案:

1、 Web代理的方式。即用户访问A网站时所产生的对B网站的跨域访问请求均提交到A网站的指定页面,由该页面代替用户页面完成交互,从而返回合适的结果。此 方案可以解决现阶段所能够想到的多数跨域访问问题,但要求A网站提供Web代理的支持,因此A网站与B网站之间必须是紧密协作的,且每次交互过程,A网站 的服务器负担增加,且无法代用户保存session状态。

2、on-Demand方式。MYMSN的门户就用 的这种方式,不过MYMSN中不涉及跨域访问问题。动态控制script标记的生成,通过修改script标记的src属性完成对跨域页面的调用。此方案 存在的缺陷是,script的src属性完成该调用时采取的方式时get方式,如果请求时传递的字符串过大时,可能会无法正常运行。不过此方案非常适合聚 合类门户使用。

3、iframe方式。查看过醒来在javaeye上的一篇关于跨域访问的帖子,他提到自己已 经用iframe的方式解决了跨域访问问题。数据提交跟获取,采用iframe这种方式的确可以了,但由于父窗口与子窗口之间不能交互(跨域访问的情况 下,这种交互被拒绝),因此无法完成对父窗口效果的影响。

(偶找到了该文,补充一下地址:http://www.javaeye.com/topic/15641)

4、 用户本地转储方式:IE本身依附于windows平台的特性为我们提供了一种基于iframe,利用内存来“绕行”的方案,即两个window之间可以在 客户端通过windows剪贴板的方式进行数据传输,只需要在接受数据的一方设置Interval进行轮询,获得结果后清除Interval即可。FF的 平台独立性决定了它不支持剪贴板这种方式,而以往版本的FF中存在的插件漏洞又被fixed了,所以FF无法通过内存来完成暗渡陈仓。而由于文件操作FF 也没有提供支持(无法通过Cookie跨域完成数据传递),致使这种技巧性的方式只能在IE中使用。

5、我自 己用于解决这类问题的方式:结合了前面几种方式,在访问A网站时,先请求B网站完成数据处理,再根据返回的标识来获得所需的结果。这种方法的缺点也很明 显,B网站的负载增大了。优点,对session也实现了保持,同时A网站与B网站页面间的交互能力增强了。最重要的一点,这种方案满足了我的全部需要。

总结一下,以上方案中可选择的情况下,我最推荐on-Demand方式,在不需要提交大量数据的情况下,这种方式能够解决您的大部分问题。

 

===============================

本地站:http://www.somedomain.com

目标站:http://bbs.somedomain.com

解决方法 :

1. 在目标站 document.domain = 'somedomain.com';

并建立一个ajax.html,引用ajax方法 (大家都叫它服务中介)

然后创建一个ajax对象 var webreq = new Ajax();

2. 在本地站 document.domain = 'somedomain.com';

用iframe引用目标站的ajax.html.

 

详细方法:

1. 本地站的一个页面(Test.html)

html:

<html>

<head>

<script type='text/javascript'>document.domain='somedomain.com';</script>

<script type='text/javascript'>

function getAjax()

{

var spn = document.getElementById('spninfo');

var bbsWin = document.getElementById('ifrWindow').contentWindow;

var Ajax = bbsWin.webreq;

Ajax.Config.Result = 'TestAjaxCross';

Ajax.Config.returnType = 'Content';

Ajax.ActionPost('http://bbs.somedomain.com/doAjax.aspx',spn);

}

</script>

</head>

<body>

<span id='spninfo' />

<input type='button' id='ajaxBtn' onclick='getAjax' value='Get' />

</body>

<iframe id='ifrWindow' src='http://bbs.somedomain.com/ajax.html' style='display:none;'></iframe>

</html>

 

/////////////////////////////////////////////////////////////////////////////

 

2. 目标站的ajax.html

Html:

<html>

<head>

<script type='text/javascript'>document.domain='somedomain.com';</script>

<script type='text/javascript' scr='http://bbs.somedomain.com/ajaxMethod.js'></script>

<script type='text/javascript'>var webreq = new Ajax();</script>

</head>

<body>

</body>

</html>

 

----------------------------------------------------------------

目标站: doAjax.aspx

html为空

doAjax.aspx.cs

代码(Page_Load)

Response.Write("<zwd><content>看到效果了么?</content></zwd>");

return;

 

=====================================================

 

AjaxMethod.js 代码

 

////////////////////Ajax////////////Class///////////////////
//Power By Gloot CopyRight @2006
//Edit Section

//Blog http://blog.sina.com.cn/tecz
//QQ 345268267
///////////////////////////////////////////////////////////

var Try = {
these: function() {
var returnValue;
for (var i = 0; i < arguments.length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
} catch (e) {}
}
//alert(123);
return returnValue;
}
}

function grr(rp) {
if(RegExp.$1)/(.*)/.exec("");
var re=new RegExp("<result>(.*)<//result>");
re.exec(rp);
if(RegExp.$1) return RegExp.$1;
return "";
}

function crr(rp) {
if(RegExp.$1)/(.*)/.exec("");
var re=new RegExp("<content>(.*)<//content>");
re.exec(rp);
if(RegExp.$1) return RegExp.$1;
return "";
}

var Ajax = function() {}
//var xhr ;这样定义不行
Ajax.prototype.Init = function(){
return Try.these(
function() {return new ActiveXObject("Msxml2.XMLHTTP")},
function() {return new ActiveXObject("Microsoft.XMLHTTP")},
function() {return new XMLHttpRequest()}
) || false;
}

Ajax.prototype.Config = {
Result:"",
SucInfo:"",
FaildInfo:"",
Url:"",
returnType:"Compare", //输入Compare是比较返回的字符是否一致,要指定Result值,//其他返回内容
ExecFunc:function(ty){
if (typeof ExecResult == 'function')
ExecResult(ty);
},
sendData:""
}

var aj = new Ajax();

Ajax.prototype.Action = function(url) { //同步
url = url + '&e='+Math.random();
var xhr = aj.Init(); 
xhr.onreadystatechange = function()
{
if (xhr.readyState == 4)
{
if (xhr.status == 200)
{
aj.FuncResult(aj.Config.Spn,xhr); 
}
}
}
xhr.open("POST",url,false);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");

xhr.send(null);

}

Ajax.prototype.Actionfor = function(url,spn) { //异步

url = url + '&e='+Math.random();
var xhr = aj.Init(); //这样写是为了多异步执行

xhr.onreadystatechange = function()
{
if (xhr.readyState == 4)
{
if (xhr.status == 200)
{
aj.FuncResult(spn,xhr); 
}
}
}
xhr.open("GET",url,true);

xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(null); 
}

Ajax.prototype.ActionAlert = function(url) //执行alert提示框的同步
{
url = url + '&e='+Math.random();
var xhr = aj.Init(); //这样写是为了多异步执行

xhr.onreadystatechange = function()
{
if (xhr.readyState == 4)
{
if (xhr.status == 200)
{
aj.AlertResult(xhr); 
}
}
}
xhr.open("GET",url,false);

xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(null);
}

Ajax.prototype.ActionPost = function(url,spn) //同步 send
{
url = url + '?e='+Math.random();
var xhr = aj.Init(); //这样写是为了多异步执行

xhr.onreadystatechange = function()
{
if (xhr.readyState == 4)
{
if (xhr.status == 200)
{
aj.postResult(spn,xhr); 
}
}
}

try {
if (netscape.security.PrivilegeManager.enablePrivilege)
{
netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
}
}catch(e) {};

xhr.open("POST",url,true);

xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//xhr.setRequestHeader("Content-Length",pars.length);
xhr.setRequestHeader("Connection", "open");
xhr.send(Webreq.Config.sendData);
}

Ajax.prototype.GetJSONData = function(url,spn)
{
url = url + '?e='+Math.random();
var xhr = aj.Init(); //这样写是为了多异步执行

xhr.onreadystatechange = function()
{
if (xhr.readyState == 4)
{
if (xhr.status == 200)
{
aj.jsonResult(spn,xhr); 
}
}
}

xhr.open("POST",url,true);

xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//xhr.setRequestHeader("Content-Length",pars.length);
xhr.setRequestHeader("Connection", "open");

xhr.send(null);
}

Ajax.prototype.onResult = function(v) {
return v==aj.Config.Result;
}

Ajax.prototype.FuncResult = function(spn,xhr)
{ //alert(spn.id);

if (aj.Config.returnType == 'Compare')
{
if (aj.onResult(grr(xhr.responseText)))
{

spn.innerHTML = aj.Config.SucInfo;
aj.Config.ExecFunc(aj.Config.Result);
if (aj.Config.Url!='')
{
window.location.href = aj.Config.Url;
}
}
else
{

spn.innerHTML = aj.Config.FaildInfo;

}
}
else
{
spn.innerHTML = crr(xhr.responseText);
aj.Config.ExecFunc(aj.Config.Result);
}

}


Ajax.prototype.AlertResult = function(xhr)
{
if (aj.Config.returnType=='Compare')
{
if (aj.onResult(grr(xhr.responseText)))
{
alert(aj.Config.SucInfo);
aj.Config.ExecFunc(aj.Config.Result);
}
else
{
alert(aj.Config.FaildInfo);
}
}
else
{
alert(crr(xhr.responseText));
aj.Config.ExecFunc(aj.Config.Result);
}
}

Ajax.prototype.postResult = function(spn,xhr)
{
if (aj.Config.returnType == 'Compare')
{
if (aj.onResult(grr(xhr.responseText)))
{
spn.innerHTML = aj.Config.SucInfo;
aj.Config.ExecFunc(aj.Config.Result);
}
else
{
spn.innerHTML = aj.Config.FaildInfo;
}
}
else
{
spn.innerHTML = crr(xhr.responseText);
aj.Config.ExecFunc(aj.Config.Result);
}
}

Ajax.prototype.jsonResult = function(spn,xhr)
{
var jsonstr = xhr.responseText;
var json = eval("return " + jsonstr);

//get data json.something json:{username:"123",content:""};

aj.Config.ExecFunc(aj.Config.Result);
}
///////////////////////////////////////////////////////////////

var WebServices = function() {}
WebServices.Config = {

}

 

分享到:
评论

相关推荐

    Javascript跨域和Ajax跨域解决方案

    JavaScript跨域和Ajax跨域是Web开发中常见的问题,尤其在进行前后端分离或API调用时,由于浏览器的同源策略限制,不同域名、协议或端口的资源请求会被阻止,这就是所谓的“跨域”。本文将深入探讨JavaScript和Ajax...

    Ajax跨域访问解决方案

    **Ajax跨域访问解决方案** 在Web开发中,Ajax(Asynchronous JavaScript and XML)技术被广泛用于实现页面的异步更新,提升用户体验。然而,由于浏览器的同源策略限制,Ajax请求只能向同源(协议、域名和端口相同)...

    Jquery跨域Ajax请求测试

    在"JqueryWebServiceTestDemo"这个示例中,可能包含了完整的前端HTML、CSS和JavaScript文件,以及可能的服务端接口文档或示例代码,用于演示如何在实际项目中运用jQuery进行跨域Ajax请求。通过学习和运行这个示例,...

    js跨域解决方案

    JavaScript跨域是Web开发中一个常见的挑战,由于浏览器的同源策略限制,JavaScript无法直接访问不同源(协议、域名或端口不一致)的资源。本文将深入探讨JS跨域的解决方案,帮助开发者理解并解决这个问题。 首先,...

    JQuery跨域访问解决方案

    JQuery的跨域解决方案主要依赖于JSONP(JSON with Padding)技术。JSONP是一种绕过同源策略的方式,它利用HTML中的`&lt;script&gt;`标签没有同源策略限制的特点。当jQuery使用`dataType: 'jsonp'`时,它实际上是在做以下几...

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

    总的来说,通过理解和利用JavaScript的跨域机制,我们可以解决AJAX在本地文件系统上的访问限制。尽管JSONP和本文中的方法在某些场景下有效,但在实际开发中,更推荐使用CORS,因为它提供了更安全、更可控的跨域访问...

    基于HTML和JavaScript的Ajax简介及跨域解决方案设计源码

    本项目为基于HTML和JavaScript的Ajax技术实践,集成了36个文件,涵盖17个HTML文件、13个JavaScript文件、4个Markdown说明文档...内容涉及Ajax基础简介及其在解决跨域问题中的应用,提供了详细的源代码和解决方案设计。

    arcgis api for javascript跨域处理方案

    总结起来,解决ArcGIS API for JavaScript的跨域问题通常需要在客户端和服务器端采取相应的措施。资源代理是一种安全且灵活的解决方案,特别是在处理敏感数据或需要控制访问权限时。理解并正确实施这些方法对于开发...

    解决ajax跨域问题

    为了解决AJAX跨域问题,开发者可以采用以下几种策略: 1. JSONP(JSON with Padding) JSONP是一种绕过同源策略的方法,它利用了`&lt;script&gt;`标签不受同源策略限制的特点。JSONP的工作原理是服务器提供一个可被调用的...

    Ajax跨域请求解决方案-JSONP

    总的来说,JSONP是Ajax跨域请求的一种实用解决方案,尤其适用于只支持GET请求且不涉及复杂交互的场景。但是,它也有一些局限性,比如不支持POST请求、无法控制HTTP头部、无错误处理机制等。因此,在现代Web开发中,...

    demo跨域ajax_DEMO_ajax跨域_

    本示例“demo跨域ajax_DEMO_ajax跨域”着重解决C#后端与JavaScript前端之间的跨域限制。这里我们将深入探讨什么是跨域、为何会产生跨域问题以及如何通过C#和Ajax实现跨域通信。 首先,我们需要了解什么是跨域。根据...

    ajax跨域解决办法

    【AJAX跨域解决办法】 在Web开发中,AJAX(Asynchronous JavaScript and XML)是一种在无需刷新整个页面的情况下更新部分网页的技术。然而,由于浏览器的同源策略限制,AJAX请求通常只能发送到与当前页面同一源的...

    ajax跨域请求WebService.asmx

    总结,Ajax跨域请求WebService.asmx是一个结合了前端JavaScript异步请求技术和后端C# Web服务交互的实例,它涉及到了跨域策略、HTTP通信、CORS配置以及JSON数据交换等多个Web开发的重要知识点。正确理解和运用这些...

    JS跨域访问解决方案总结.pdf

    标题《JS跨域访问解决方案总结.pdf》指明文档的核心内容是关于JavaScript跨域访问问题的解决方法。跨域访问问题是指由于浏览器的同源策略限制,网页中JavaScript代码出于安全原因不能访问另一个源(域名、协议或端口...

    Ext.Ajax.request跨域

    在IT行业中,跨域是Web开发中一个常见的挑战。...通过理解和运用CORS,我们可以利用Ext.Ajax.request在ExtJS应用中安全地进行跨域通信。同时,深入研究`domain.js`文件将有助于我们掌握具体实现细节。

    ajax处理跨域请求

    在Web开发中,由于浏览器的同源策略限制,JavaScript通常无法直接访问不同源(协议、域名或端口不同)的资源。然而,随着互联网应用的...在实际项目中,开发者应根据具体需求和服务器支持情况选择合适的跨域解决方案。

    JavaScript语言与Ajax应用第二版_JavaScript语言与Ajax应用_JavaScript应用_javascri

    Ajax,全称Asynchronous JavaScript and XML(异步JavaScript和XML),是一种创建动态网页的技术,允许在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容。在"JavaScript语言与Ajax应用(第二版)...

    JS跨域访问解决方案总结

    1. **JSONP (JSON with Padding)**: JSONP是一种早期的跨域解决方案,适用于GET请求。它通过在HTML中动态插入`&lt;script&gt;`标签来实现。服务器返回的不是JSON数据,而是一个函数调用,将JSON数据作为参数传递。例如,`...

Global site tag (gtag.js) - Google Analytics