`

AJAX 跨域访问 — 方法大全

阅读更多

Case I. Web代理的方式 (on Server A)

 

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

 

Case II. on-Demand方式 (on Server A)

 

MYMSN的门户就用的这种方式,不过 MYMSN中不涉及跨域访问问题。在页面内动态生成新的<script>,将其src属性指向别的网站的网址,这个网址返回的内容必须是合法的Javascript脚本,常用的是JSON消息。此方案存在的缺陷是, script的src属性完成该调用时采取的方式时get方式,如果请求时传递的字符串过大时,可能会无法正常运行。不过此方案非常适合聚合类门户使用。

 

<html>
<head>
<script language="javascript" type="text/javascript">
function loadContent()
{
var s=document.createElement('SCRIPT');
s.src='http://www.anotherdomain.com/TestCrossJS.aspx?f=setDivContent';
document.body.appendChild(s);
}

function setDivContent(v)
{
var dv = document.getElementById("dv");
dv.innerHTML = v;
}
</script>
</head>
<body>
<div id="dv"></div>

<input type="button" value="Click Me" onclick="loadContent()">
</body>
</html>

其中的www.anotherdomain.com/TestCrossJS.aspx是这样的,

<script language="C#" runat="server">
void Page_Load(object sender, EventArgs e)
{
  string f = Request.QueryString["f"];
  Response.Clear();
  Response.ContentType = "application/x-javascript";
  Response.Write(String.Format(@"
                   {0}('{1}');", 
                   f,
                   DateTime.Now));
  Response.End();
}
</script>

点击“Click Me”按钮,生成一个新的script tag,下载对应的 Javascript 脚本,结束时回调其中的setDivContent(),从而更新网页上一个div的内容。

 

 

Case III. iframe方式 (on Server A)

 

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

在页面内嵌或动态生成指向别的网站的IFRAME,然后这2个网页间可以通过改变对方的anchor hash fragment来传输消息。改变一个网页的anchor hash fragment并不会使浏览器重新装载网页,所以一个网页的状态得以保持,而网页本身则可以通过一个计时器(timer)来察觉自己anchor hash的变化,从而相应改变自己的状态。

 

1. http://domain1/TestCross.html:

<html>
<head>
<script language="javascript" type="text/javascript">
var url = "http://domain2/TestCross.html"
var oldHash = null;
var timer = null;

function getHash()
{
var hash = window.location.hash;
if ((hash.length >= 1) && (hash.charAt(0) == '#'))
{
hash = hash.substring(1);
}

return hash;
}
function sendRequest()
{
var d = document;
var t = d.getElementById('request');
var f = d.getElementById('alienFrame');
f.src = url + "#" + t.value + "<br/>" + new Date();
}

function setDivHtml(v)
{
var d = document;
var dv = d.getElementById('response');
dv.innerHTML = v;
}

function idle()
{
var newHash = getHash();

if (newHash != oldHash)
{
setDivHtml(newHash);
oldHash = newHash;
}

timer = window.setTimeout(idle, 100);
}

function window.onload()
{
timer = window.setTimeout(idle, 100);
}
</script>
</head>
<body>

请求:<input type="text" id="request"> <input type="button" value="发送" onclick="sendRequest()" /><br/>
回复:<div id="response"></div>

<iframe id="alienFrame" src="http://domain2/TestCross.html"></iframe>

</body>
</html>

2. http://domain2/TestCross.html:

<html>
<head>
<script language="javascript" type="text/javascript">
var url = "http://domain1/TestCross.html"
var oldHash = null;
var timer = null;

function getHash()
{
var hash = window.location.hash;
if ((hash.length >= 1) && (hash.charAt(0) == '#'))
{
hash = hash.substring(1);
}

return hash;
}
function sendRequest()
{
var d = document;
var t = d.getElementById('request');
var f = parent;
//alert(f.document); //试着去掉这个注释,你会得到“Access is denied”
f.location.href = url + "#" + t.value + "<br/>" + new Date();
}

function setDivHtml(v)
{
var d = document;
var dv = d.getElementById('response');
dv.innerHTML = v;
}

function idle()
{
var newHash = getHash();

if (newHash != oldHash)
{
setDivHtml(newHash);
oldHash = newHash;
}

timer = window.setTimeout(idle, 100);
}

function window.onload()
{
timer = window.setTimeout(idle, 100);
}
</script>
</head>
<body>

请求:<input type="text" id="request"> <input type="button" value="发送" onclick="sendRequest()" /><br/>
回复:<div id="response"></div>

</body>
</html>

两个网页基本相同,第一个网页内嵌一个IFRAME,在点击“发送”按钮后,会将文本框里的内容通过hash fragment传给IFRAME。点击IFRAME里的“发送”按钮后,它会将文本框里的内容通过hash fragment传给父窗口。因为是只改动了hash fragment,浏览器不会重新load网页内容,这里使用了一个计时器来检测URL变化,如果变化了,就更新其中一个div的内容 。 

 

Case IV. 用户本地转储方式 (local)

 

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

 

 

Case V: (其实还是在服务端A用iframe解决了与服务器B通信的问题)

 

要解决的问题:发生在用户提交网页 URL (还包括 Tag, Notes 等)给 Bookmark 服务器时。

关于 URL 的提交至少可以有三种方式:

 

1.       登陆 Bookmark 服务器的提交页面,将要收藏的 URL 通过该页面提交给服务器。

2.       安装浏览器插件,通过插件将 URL 提交给服务器。

3.       Bookmark 服务器动态加载 javascript 小工具到当前页面,通过它来完成提交工作。

 

    第一种方式开发起来最简单,但对用户来讲比较麻烦,每次都需要先登陆 Bookmark 服务器才能完成提交;第二种方式我并不熟悉插件开发,而且用户也不喜欢太多的插件堆满自己的浏览器;第三种方式开发难度小,又避免了每次登陆服务器的麻烦,所以最终采用它。第三种方式中动态加载的 javascript 小工具除了需要生成 UI 供用户填写信息( URL tag notes 等),当用户点击提交的时候,还要完成与服务器通信的功能。

 

     跨域访问,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容。由于安全原因,跨域访问是被各大浏览器所默认禁止的。写过跨域访问 ajax 的朋友相信都遇到过被告知“没有权限”的情况。通过 XMLHttp 来发送数据给 Bookmark 服务器的尝试失败了。于是,看到网上的一些资料,我又开始尝试用 javascript 小工具在用户网页动态创建一个隐藏的 iframe, iframe src 指向服务器的一个 servlet ,试图通过调用 iframe 中提供的 javascript 来完成与服务器的通信。但不幸的是,用户网页中的 javascript 代码访问 iframe 也被浏览器归为跨域访问(特指 iframe src 指向其它网站的情形),尝试再次失败。

 

最终,在一篇文章中看到,与 iframe 不同,如果 A 网站从 B 网站加载 javascript A 网站可以自由的访问该 javascript 的内容,并不会被浏览器认为是跨域访问。模仿刚才 iframe 的思路,当用户点击提交时,可以动态创建一个 javascript 对象,该对象的 src 指向 Bookmark 服务器的一个 servlet ,注意: URL Tag Notes User Password 等信息被作为 src URL 参数传给服务器。请看下面的代码:

 

 

var url = "http://localhost:8080/Deeryard/BookmarkServlet?" +

           "url=" + url_source + "&" + "title=" + title + "&" +

"tag=" + tag + "&" + "notes=" + notes + "&" + "user=" + user + "&" + "password=" + password;

 

url = encodeURI(url);

   

//Submit to server with a trick

var js_obj = document.createElement( "script" );

js_obj.type = "text/javascript" ;

js_obj.setAttribute( "src" , url);

   

//Get response from server by appending it to document

document.body.appendChild(js_obj);

 

 

上面例子中, js_obj.setArrribute() 将信息作为 src URL 参数提交给了 Bookmark servlet 。那么用户又如何取得服务器的响应信息呢?答案就是最末一行代码, servlet 的输出必须是 javascript 代码,它可以调用用户网页上的其他 javascript 函数,以及操作 dom 对象。下面的 servlet 代码生成了一个 javascript 函数调用:

 

out.write("onServerResponse(INADEQUATE_INFORMATION);");

 

document.body.appendChild(js_obj) 执行后 onServerResponse( INADEQUATE_INFORMATION) 就会得到执行,使客户网页响应服务器结果。这样一个完整的通信过程就完成了。

 

CaseVI:Tomcat + PHP + HTML(含JS)(on Server A)

 

服务器A上已经装好了Tomcat, 我们写一个test.html(含JS),再写一个PHP文件(由其来完成跨域通信要求)。

 

更多地,请参考:https://www6.software.ibm.com/developerworks/cn/education/xml/x-ajaxtrans/index.html

http://www.xyhhxx.com/news/net/20061013121041.htm

 

分享到:
评论
5 楼 zhng 2012-02-23  
mark,今天电面问到这个问题,还没接触过,临时报佛脚。
4 楼 jssay 2011-09-28  
有时间一定要拜读一下,楼主辛苦了!
3 楼 HK.Night 2011-09-01  
1024~~~
2 楼 zhaozk 2011-01-10  
mark too
1 楼 mrlee09 2010-09-01  
mark mark mark

相关推荐

    Ajax跨域访问(ASP.NET Web)

    本教程将重点讲解如何在ASP.NET Web环境中处理Ajax跨域访问。 一、理解同源策略 同源策略是浏览器为了保护用户安全而实施的一项安全机制,它禁止了一个源(domain)的文档或脚本获取或操作另一个源的资源。这意味着...

    ajax跨域解决办法

    AJAX跨域问题的出现是由于浏览器的安全机制,旨在防止恶意网站通过脚本访问其他网站的数据,保护用户隐私。但是,在某些场景下,比如前后端分离的应用、API接口调用等,跨域请求是必要的。针对这一需求,有多种解决...

    Ajax跨域访问解决方案

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

    怎样实现Ajax 跨域访问

    本文将详细介绍五种实现Ajax跨域访问的方法。 #### 一、使用JSONP(JSON with Padding) JSONP是一种常用的跨域数据获取方式,其原理是利用`&lt;script&gt;`标签没有跨域限制的特点来实现跨域请求。请求时,在URL中添加...

    JAVA的AJAX跨域访问

    ### JAVA的AJAX跨域访问:深入解析与解决方案 #### 引言 在现代Web开发中,AJAX(Asynchronous JavaScript and XML)技术被广泛应用于实现网页的异步加载,从而提升用户体验。然而,AJAX请求的一个常见问题就是...

    JQury实现Ajax跨域访问

    **jQuery实现Ajax跨域访问** 在Web开发中,由于同源策略的限制,JavaScript通常只能对同一域名下的资源进行操作。然而,有时我们需要从不同源获取数据,这就是跨域访问的需求。jQuery通过Ajax提供了跨域请求的能力...

    ajax跨域访问案例.zip

    个人学习时编写的代码,该案例用于演示Ajax的跨域访问问题。!!!补充说明:导入工程时需要选择导入maven工程!上传仅为学习交流,也为自己下载方便!水平有限不喜勿喷。在README.txt中有对项目的详细说明!

    Ajax跨域传输参数

    可以将book.aa.com用iframe添加到 www.aa.com的某个页面下,在www.aa.com和iframe里面都加上document.domain = "aa.com",这样就可以统一域了,可以实现跨域访问。就和平时同一个域中镶嵌iframe一样,直接调用里面的...

    Javascript跨域和Ajax跨域解决方案

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

    demo跨域ajax_DEMO_ajax跨域_

    以上就是C#和Ajax跨域通信的基本原理和实现方法。在实际应用中,还需考虑安全性,谨慎设置允许跨域的源,以及是否允许携带Cookie等认证信息。通过理解并正确实施这些策略,你可以确保C#服务器与任何合法源的前端应用...

    Ajax通过代理跨域访问

    本文将详细探讨两种主要的Ajax跨域访问解决方法:JSONP和CORS。 **1. JSONP(JSON with Padding)** JSONP是一种非官方的跨域数据交互协议,它利用了`&lt;script&gt;`标签不受同源策略限制的特点。JSONP的工作原理是:...

    JSONP实现Ajax跨域访问

    ### JSONP实现Ajax跨域访问 #### 一、引言 JSONP(JSON with Padding)是一种用于解决跨域数据访问的技术。由于同源策略(Same-Origin Policy)的存在,JavaScript/Ajax只能请求同源的资源,这给需要跨域访问数据...

    Ajax跨域详解与代码

    **二、解决Ajax跨域的常见方法** 1. **CORS(Cross-Origin Resource Sharing)跨域资源共享**:服务器端设置响应头`Access-Control-Allow-Origin`,指定允许跨域访问的源。例如,设置为`*`表示允许所有来源,或者...

    ajax跨域调用wcf实例

    确保只允许可信的源进行跨域访问,并对敏感操作进行身份验证和授权。 通过以上步骤,你可以成功地使用AJAX跨域调用WCF服务。在实际项目中,需要根据具体需求调整配置,并结合安全措施,以确保服务的稳定性和安全性...

    Spring Boot Redis Session 共享(Ajax 跨域)

    在现代Web应用开发中,数据共享和跨域访问是常见的需求。Spring Boot作为一个轻量级的框架,提供了方便快捷的方式来实现这些功能。本教程将详细讲解如何在Spring Boot项目中利用Redis来存储和共享Session,并解决...

    ajax跨域访问

    ### AJAX跨域访问详解 #### 一、引言 在Web开发中,由于浏览器的安全策略限制,同源策略(Same-origin policy)成为了跨域请求的一大障碍。为了克服这一限制,AJAX通过多种技术实现了跨域数据获取。其中,JSONP...

    Ext.Ajax.request跨域

    CORS通过在服务器端设置`Access-Control-Allow-Origin`响应头来允许特定的源进行跨域访问。当`Access-Control-Allow-Origin`值为`*`时,表示任何源都可以访问;如果指定具体的域名,那么只有该域名下的页面可以访问...

Global site tag (gtag.js) - Google Analytics