简明现代魔法 -> Ajax技术 -> 跨域的理解与实现

跨域的理解与实现

2010-05-25

域(Domain)是Windows网络中独立运行的单位,域之间相互访问则需要建立信任关系(即Trust Relation)。信任关系是连接在域与域之间的桥梁。当一个域与其他域建立了信任关系后,2个域之间不但可以按需要相互进行管理,还可以跨网分配文件和打印机等设备资源,使不同的域之间实现网络资源的共享与管理。 有一种简明的说法来解释广域跨域:跨域访问,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容。由于安全原因,跨域访问是被各大浏览器所默认禁止的。

在广域网环境中,由于浏览器的安全限制,网络连接的跨域访问时不被允许的,XmlHttpRequest也不例外。但有时候跨域访问资源是必需的。

同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。这意味着浏览器隔离来自不同源的内容,以防止它们之间的操作。同源策略不阻止将动态脚本元素插入文档中。

参考理论一:在浏览器中不能直接来跨域访问,而在服务器端没有跨域安全限制。

这样的话,可以在服务端完成跨域访问,而在客户端来取得结果就可以了。

参考理论二:同源策略不阻止动态脚本元素插入,脚本访问可以跨域。

用服务器端的XmlHttpRequest代理实现跨域访问

我们不能在浏览器端直接使用AJAX来跨域访问资源,但是在服务器端是没有这种跨域安全限制的。所以,我们只需要让服务器端帮我们完成“跨域访问”的工作,然后在浏览器端用AJAX获取服务器端“跨域访问”的结果就可以了。这就是所谓的在服务器端创建一个XmlHttpRequest代理,通过这个代理来访问其他域名下的资源。这里引用Yahoo! JavaScript Developer Center上的几张图来进一步说明这个方案:

使用XmlHttpRequest访问同一域名下的资源:

使用XmlHttpRequest跨域访问资源:

用服务器端的XmlHttpRequest代理来跨域访问资源:

编写服务器端XmlHttpRequest代理的具体过程就不赘述了,无非是创建一个自定义的HTTP请求。

用动态script标签实现客户端的跨域访问

很明显,上一个方案必须要在服务器端做相应的改动才能实现跨域访问。但是有些时候,用户不能改动服务器端的源代码,而且更多的时候,用户并没有Web开发的基础,他们只会简单的复制、粘贴操作。这个时候,第一个方案就不能满足一个服务提供者的需求了。

我们应该能注意到,虽然浏览器有跨域访问的限制,但是我们是可以通过script标签远程引用其他域名下的脚本文件的。而且,script标签的 src属性不一定必须是一个存在的js文件,也可以是一个http handler的url,只要这个http handler返回的是一个text/javascript类型的响应就可以了。

这样,我们的第二个方案就浮出水面了。只要让用户添加一个script标签,这个script标签的src属性指向我们api的url,并提供 api需要的一些参数,通常其中包括了一个作为callback的js函数名。针对这个脚本请求,我们服务器端的http handler会根据url中携带的参数,生成并返回相应的脚本,通常这个脚本的内容是调用callback函数,并传入用户需要的数据作为参数。于是,一个跨域访问的过程就完成了。下面是一个Yahoo! JavaScript Developer Center上提供的一个例子:

<html> 
<head> 
<title>How Many Pictures Of Madonna Do We Have?</title> 
<script type="text/javascript"> 
function ws_results(obj) 
{ 
	alert(obj.ResultSet.totalResultsAvailable); 
} 
</script> 
<script type="text/javascript" src="http://search.yahooapis.com/ImageSearchService/V1/imageSearch?appid=YahooDemo&query=Madonna&output=json&callback=ws_results"></script> 
</head> 
<body>
</body> 
</html> 

将这段代码复制到文本编辑器中,另存为xxx.html,再将另存到文件拖到浏览器中,就能看到效果了(网速慢的话需要等待一下)。在这个例子中,api的url的callback参数指定了跨域访问成功后会调用的函数的名称,这个函数有一个参数,这个参数就是用户跨域访问需要的数据,通常是一个json对象。

这个例子有一个不足之处,就是这个跨域访问实际上是“静态的”,也就是说不能随时动态的实现跨域访问,例如同一个按钮点击事件来触发跨域访问。其实只要将代码稍微修改一下,就可以实现动态的跨域访问了,下面是修改后的代码:

<html> 
<head> 
<title>How Many Pictures Of Madonna Do We Have?</title> 
<script type="text/javascript"> 
function ws_results(obj) 
{ 
	alert(obj.ResultSet.totalResultsAvailable); 
} 
 
function onClick() 
{ 
	var script = document.createElement("script"); 
	script.type = "text/javascript"; 
	script.src = "http://search.yahooapis.com/ImageSearchService/V1/imageSearch?appid=YahooDemo&query=Madonna&output=json&callback=ws_results"; 
	document.body.appendChild(script); 
} 
</script> 
</head> 
<body> 
<input type="button" value="click me!" onclick="onClick()"> 
</body> 
</html>

服务器端的http handler处理请求的过程这里也不赘述了,关键就是根据用户的参数生成js代码。

其他实现跨域访问的方案

除了上面两种方案之外,还有其他一下方法同样可以实现跨域访问,例如:

Javascript跨域和Ajax跨域解决方案

Ajax跨域和JS的跨域通信(Cross The Site)的几种解决方案

最近做的一个项目中需要ajax跨域取得数据,如果是在本域中确实没有问题,但是放到二级域和其他域下浏览器直接就弹出提示框:“该页正在访问其控制范围之外的数据,这有些危险,是否继续"。

什么引起了ajax跨域不能的问题?ajax本身实际上是通过XMLHttpRequest对象来进行数据的交互,而浏览器出于安全考虑,不允许js代码进行跨域操作,所以会警告。

有什么完美的解决方案么?没有。解决方案有不少,但是只能是根据自己的实际情况来选择。

具体情况有:

解决方法:

总结:

随机文章推荐
网站分类


注:如需转载本文,请注明出处(原文链接),谢谢。更多精彩内容,请进入简明现代魔法首页。

进入新博客
喜欢本文,就分享它吧
给我留言
您的名字:
您的邮件:
您的网站:


 

copyright © 2009 简明现代魔法    学习、分享、进步

power by Gonn 感谢所有关心和支持本站的朋友们