`
yysct2005
  • 浏览: 90691 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

浏览器跨域获取特定域的数据的办法

阅读更多

浏览器跨域获取特定域的数据的办法

|

以前看了几篇这方面的文章,但是都未能找到一个合适的解决方法。
获取同一个域的数据,可以通过XMLHTTP组件或IFRAME来实现,不存在跨域访问的权限问题,因此比较简单。
但如果要访问不同域的数据时,由于浏览器的安全设置,XMLHTTP没有权限获取数据,而IFRAME没有权限将获取的数据传递给父窗口,似乎没有其它解决办法。
在网上提到的方法,不外乎这两种:
1. 如果要获取的数据位于同一个根域但是不同子域时,可以在脚本中指定document.domain为父域。
2. 如果要获取的数据位于不同的根域时,则可以在服务器上写一个脚本作为代理,由服务器上的脚本获取不同域的数据,然后传递给在同一个域中的网页。
以上两种方法很容易便能想到,现在的问题是,如果要获取一个不同根域的数据时,该如何实现?

一般我们不会漫无目的地去网上获取数据,往往是从指定的服务器上获取数据,就像Google MapsGoogle Adsensereferer这样的网页插件,一般都是以脚本的形式提供给用户使用的。这时,如果要求用户在自己的服务器上写个代理的话,易用性就要大打折扣。获取你会考虑为用户写好各种脚本的代理,PHP、ASP、Python、Perl……,但是,如果这台服务器不支持动态脚本,又该怎么办呢?
想了两天都没想通这个问题(除去上班时间其实不到两个小时),曾考虑过用浏览器的漏洞来实现,但是这样做不能长久,因此放弃。随后发现Google本地搜索的地图数据来自于mapabc.com,好家伙,他们是怎么办到的?
用FireFox的DOM查看器可以看到,地图区是一个IFRAME,难道是用IFRAME实现的?但是拖动地图时如何知道要下载哪些图片的?这些数据是一定要从服务器上获取的,难道放这些数据的服务器也是google.com域内的?应该不会这么麻烦。
随即找来Google Maps的API进行开刀,官网给的范例网页如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Maps JavaScript API Example</title>
<script src="http://maps.google.com/maps?file=api&v=2&key=abcdefg"
type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[

function load() {
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
}
}

//]]>
</script>
</head>
<body onload="load()" onunload="GUnload()">
<div id="map" style="width: 500px; height: 300px"></div>
</body>
</html>

 

把http://maps.google.com/maps?file=api&v=2&key=abcdefg下载下来看了一下,里面有一句:

GScript("http://maps.google.com/mapfiles/maps2.67.api.js");
这句就是用来加载地图操作库的,GScript函数定义为:
function GScript(src) {document.write('');}
顿悟……
网页内引用不同域的脚本并不会提示权限不足,对了,就是它没错!
这个方法其实我早应该想到的,可能是太久没玩javascript的缘故吧。不论是referer还是Google Analytics,要统计页面访问信息,都要用脚本来向服务器提交信息,只是它们只提交一次(Google Analytics有统计逗留时间,应该有好几次)。习惯性地,我把提交和下载数据分开了,所以不容易想到这个方法。
但是用document.write始终不是好办法,它会清除页面上原有的内容。改进的方法估计你已经想到了,可以参考一下我很早以前乱写的这篇文章《有效地组织页面中复杂的JavaScript脚本》里的思想。
继续分析Google Maps的代码,打开http://maps.google.com/mapfiles/maps2.67.api.js,里面有这样的代码:
ta.prototype.Hk=function(a,b){var c=this.ql(a);if(c){window.setTimeout(function(){b(c)},
0)}else{var d="__cg"+Zf++ +(new Date).getTime();try{if(this.qe==null){this.qe=document.getElementsByTagName("head")[0]}var e=window.setTimeout(sd(d,b,a,403),15000);if(!window.__geoStore){window.__geoStore={}}window.__geoStore[d]=Jf(this,d,b,e);var f=document.createElement("script");f.type="text/javascript";f.id=d;f.charset="UTF-8";f.src=this.vl+"?q="+window.encodeURIComponent(a)+"&output=json&callback=__geoStore."+d+"&key="+this.Lh;this.qe.appendChild(f)}catch(g){if(e){window.clearTimeout(e)}window.setTimeout(sd(d,
b,a,500),0)}}};
script节点也是动态创建的,这样就可以避免document.write产生的问题。

 

解决方法找到了,现在来简单测试一下:
1. 在本地服务器上新建一页面。
test.html:

<html>
<head>
<title> Over-Domain Data Fetching Test Page</title>
<script type="text/javascript">
var lastScript;
var h=document.getElementsByTagName("head")[0];</code>

function loadScript(url){
var f=document.createElement("script");
var d=new Date().getTime();
f.type="text/javascript";
f.id=d;
f.src=url+'?'+d;
h.appendChild(f);
if(lastScript&&g(lastScript))g(lastScript).parentNode.removeChild(g(lastScript));
lastScript=d;
}

function g(x){return document.getElementById(x)};
</script>
</head>

<body>
<button onclick="loadScript('http://localhost/alert.js')">Test Alert</button><br />
<button onclick="loadScript('http://localhost/info.js')">Get My Info</button><br />
My Name: <input id="myname" type="text" value="" /><br />
My Blog: <input id="myblog" type="text" value="" />
</body>
</html>
解释两个关键点:
1. lastScript用于存放上次建立的script节点的ID,在下次要再新建script节点时,要删除上次建立的节点,以免加载的脚本越来越多,占用过多的内存。
2. url后面加了一个数值d是为了防止浏览器缓存脚本数据,在本例中可以不加,但是如果脚本是由服务器动态生成的,那最好加上。
然后再建立两个javascript脚本用于测试:
alert.js:
alert('You can see me!');
info.js:
g('myname').value='Hily Jiang';
g('myblog').value='http://hily.iyi.cn/';
好了,把它们放在本地服务器的根目录下,敲入http://127.0.0.1/test.html,这样它和localhost就不在同一个域内了。
点击“Test Alert”,应该会弹出对话框显示You can see me!。
点击“Get My Info”,应该会在文本框中显示我的信息。
(以上测试页在IE 6.0和FireFox1 .5.0下测试通过。)
分享到:
评论

相关推荐

    Ajax +jquery跨域获取JSON

    对于"跨域获取JSON",通常Web浏览器遵循同源策略,限制了JavaScript从不同源获取数据的能力。为了解决这个问题,我们可以利用JSONP(JSON with Padding)或者CORS(Cross-Origin Resource Sharing)机制。JSONP是一...

    完美解决iframe跨域问题

    3. **iframe跨域问题**:当iframe加载的页面与包含它的页面不在同一个域时,就会出现跨域问题,导致无法直接通过JavaScript进行通信,如获取iframe内的内容、设置iframe的属性等。 **二、iframe跨域的解决方案** 1...

    完美解决浏览器跨域的几种方法(汇总)

    JSONP适合简单数据获取,window.name适合单向传递大量数据,document.domain用于子域间通信,window.postMessage适用于现代浏览器的双向通信,而服务器代理则提供了更灵活的解决方案,尤其适用于需要处理复杂请求和...

    jquery跨域调用 js跨域调用

    浏览器会执行这个函数,从而达到跨域获取数据的目的。 2. jQuery中使用JSONP:jQuery的`$.ajax()`方法支持`dataType: 'jsonp'`,自动处理JSONP请求。用户只需提供回调函数名,jQuery会生成一个唯一的函数名插入到URL...

    javascript插件 解决双向跨域问题

    跨域(Cross-Origin)是一个常见的问题,特别是在Web开发中,当尝试从一个源(如一个域名、协议或端口)加载资源到另一个源时,浏览器的安全策略通常会阻止这种行为,以防止恶意脚本从不受信任的来源获取数据。...

    用YQL和Jquery实现的跨域html页面截取

    综上所述,"用YQL和Jquery实现的跨域html页面截取"的解决方案巧妙地结合了YQL的跨域能力和jQuery的JSONP请求功能,实现了在前端获取和处理其他域的HTML内容,这对于数据聚合、分析或者构建Web应用等场景十分有用。...

    AJAX跨域请求JSONP获取JSON数据的实例代码

    总结起来,JSONP是一种通过JavaScript回调函数实现的跨域数据交换技术,主要用于那些不支持CORS或者需要兼容旧版浏览器的应用场景。然而,由于其局限性,随着CORS的普及,JSONP在现代Web开发中的使用正在逐渐减少。

    普元eos跨域组件

    跨域是由于浏览器的同源策略产生的,这个策略是为了防止恶意脚本通过JavaScript获取并操作其他网站的数据。然而,在现代Web应用中,前端和后端往往不在同一个域下,这就需要一种方式来规避同源策略的限制。普元EOS的...

    处理session跨域几种方案

    Session是Web应用程序用来存储用户特定数据的一种机制,通常存储在服务器端,而Session ID通过Cookie在客户端与服务器之间传递。当用户在不同域之间跳转时,如果不进行特殊处理,Session信息将无法跨域共享。 以下...

    jsonp解决跨域_js_方案_web_跨域_

    随着Web应用的复杂性增加,前端和后端的分离越来越普遍,前端页面可能需要从多个服务器获取数据,这就产生了跨域的需求。同时,Ajax技术的兴起,使得动态交互成为可能,跨域通信成为提升用户体验的重要手段。 **三...

    实现跨域例子内附说明.zip

    或者只允许特定域访问: ``` Access-Control-Allow-Origin: http://example.com ``` 其他关键响应头包括: - `Access-Control-Allow-Methods`:指定允许的HTTP方法。 - `Access-Control-Allow-Headers`:指定...

    JS跨域访问解决方案总结

    JSONP(JSON with Padding):利用`&lt;script&gt;`标签可以跨域加载脚本的特性,通过动态创建`&lt;script&gt;`标签,指定其`src`属性为服务端提供的带有回调函数的URL,服务端返回JSON数据包裹在回调函数中,达到跨域获取数据的...

    cesium在Tomcat部署后,跨域访问问题解决.zip

    在IT行业中,尤其是在Web开发领域,跨域访问问题是一个常见的挑战。Cesium是一个强大的JavaScript库...在实际项目中,应根据具体的安全需求和应用架构,适当调整跨域策略,确保既能满足功能需求,又能保证数据的安全。

    MVC+WebAPI跨域调用.rar

    在这个例子中,WebAPI需要配置以允许来自特定域的jQuery请求。 2. **JSONP(JSON with Padding)**:JSONP是一种早期的跨域解决方案,适用于只支持GET请求的API。它通过动态创建`&lt;script&gt;`标签,利用其可以跨域加载...

    跨域弹窗传值

    `,然后父窗口可以通过检查`someData`来获取数据。但是,这种方法受到同源策略的限制,如果父窗口和子窗口不在同一个域,浏览器会阻止这种操作。 2. **使用`postMessage`和`message`事件**: `window.postMessage`...

    getJSON解决 跨域问题例子

    在IT行业中,跨域问题是一个常见的挑战,尤其是在Web开发中,因为浏览器的同源策略(Same-Origin Policy)限制了JavaScript从一个源获取另一个源的数据。本篇将详细讲解如何使用getJSON来解决跨域问题,以及涉及到的...

    js跨域问题解决方案.

    这一策略限制了恶意脚本获取和操作其他站点的数据,但也给跨域数据交换带来了困扰。 ### 2. 跨域问题的类型 - **文档加载跨域**:如iframe加载不同源的页面。 - **Ajax请求跨域**:XMLHttpRequest或Fetch API发送...

    跨域测试文件网页的直接测试.zip

    如果一个域下的脚本试图请求另一个域的资源,就会触发跨域请求,而浏览器默认会阻止这种行为,以防止恶意网站获取用户在另一网站上的敏感信息。 跨域测试通常包括以下几个方面: 1. **CORS(Cross-Origin Resource...

    WebUploadTest(跨域)

    在Web应用中,跨域是指一个域下的文档或脚本尝试访问另一个域下的资源。由于浏览器的安全策略——同源策略,不同源的HTTP请求会被禁止,除非服务器明确允许。同源策略是防止恶意网站窃取用户信息的重要防线,但同时...

    arcgis api for javascript跨域处理方案

    ArcGIS API for JavaScript是一个强大的工具,用于在Web页面上展示地理信息系统(GIS)数据,但它的功能涉及到从服务器获取地图、服务和其他资源,这可能导致跨域访问的问题。为了解决这个问题,我们可以采用几种...

Global site tag (gtag.js) - Google Analytics