Javascript 跨域访问解决方案


Posted in Javascript onFebruary 14, 2009

这里分两类情况:
一、基于同一父域的子域之间页面的访问;参见如下3个domain域:taobao.com、jipiao.taobao.com、promotion.taobao.com;它们有相同的父域taobao.com。
二、基于不同父域页面之间的访问;参见如下3个domain域:taobao.com、baidu.com、sina.com.cn;它们具有不同的父域。

解决它们之间跨域的方案有:
方案1:服务器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"><!-- 
Var sUrl="http://Jipiao.taobao.com/proxy.do"; //本域下代理地址 
var callback = 
{ 
success: function(res) { alert(res.responseText); }, 
failure: function(res) { alert('failure');}, 
argument:{} 
} 
YAHOO.util.Connect.asyncRequest('GET', sUrl, callback, null); 
// --></script>

第二步:
完成域A服务端的Proxy程序(这里假定是一个servlet),伪码如下:
Public class Proxy extends …….{ 
..doGet(……..){ 
HttpClient client=……; 
GetMethod get=new GetMethod("www.baidu.com/xxxxx.do");//访问域B的链接 
int statusCode = client.executeMethod(get); 
if (statusCode != HttpStatus.SC_OK) { 
byte[] responseBody = get.getResponseBody(); 
String res=new String(responseBody); 
Httpresponse.getWriter().write(res);//将数据返回给域A 
} 
} 
}

方案2:通过Script标签:
在域A页面http://Jipiao.taobao.com/test.htm 的head中写一个空的Script标签:
<html> 
<head> 
<script id="remoteScript" type="text/javascript" src=""/><!-- 
<head> 
<body> 
<script type="text/javascript" > 
Var remoteScript=document.getElementById("remoteScript"); 
remoteScript.src="www.baidu.com/xxxxx.do";//域B的链接 
alert(remote.test);//使用域B返回的JSON数据 
alert(f[0]); 
// --></script> 
</body> 
</html>

注意:这种方案要求域B返回的数据必须是合法的JSON格式或者如JS文件的格式;比如域B返回的数据格式如下:
Var remote={test:'hello'};
Var f=[2,1];

方案3:隐藏iframe、共享domain:
即域A页面http://jipiao.taobao.com/yyyy.htm 的页面上写一个隐藏的iframe:

<html> 
<head> 
<head> 
<body> 
<script type="text/javascript" ><!-- 
Document.domain="taobao.com"; 
Var remoteHtml=document.getElementById("remoteHtml"); 
remoteHtml.src="promotion.taobao.com/xxxx.htm";//这里访问域B的链接 
var document=remoteHtml.ContentDocument; //这里就可以使用document来操作域B中页面xxx.htm的数据了 
// --></script> 
<iframe id="remoteHtml" src="" style="diapay:none" style="diapay:none"/> 
</body> 
</html>

注意:这里http://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格式数据,如果是其他格式的数据,那么这种方法就无能为力了。
隐藏iframe方式也很简单,它可以处理任何返回的数据格式,但它只适用在具有同一个父域下的跨域请求上,并且要求其他域得配合开发,即需要设置document.domain。
原帖详见:http://blog.csdn.net/lovingprince/archive/2008/09/20/2954675.aspx
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
对于JS跨域访问的意思,我想再补充几点:
跨域访问,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容;比如想从A网站的页面中执行另外一个B网站内某页面中的JS对象、或者想在A网站的页面中用JS去解析B网站内某页面的dom元素等;出现这种跨域访问问题的应用场景一般是iframe中嵌入不同域的页面、或者向不同域发送Ajax请求等;
由于安全原因,跨域访问是被各大浏览器所默认禁止的;但是浏览器并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function;这点个人觉得至关重要!
是否跨域的判断规则为对三者进行比较:域名、协议、端口;三者中若有一个不相同,则会出现跨域问题;我们经常说的跨域问题一般指域名不同,因为这种场景出现的几率最高而且有一些办法可以解决;比如前面提到的taobao.com域下的二级域名跨域问题;
对于主域都不一样、或者协议不同(比如https与http)的跨域问题(比如*.taobao.com域想访问*.baidu.com域内的内容),想从Web端来解决是完全不可能的,只能通过服务端Proxy的方案来解决;
常见的不同域间的页面制约dom元素包括:
window.location 可以设置,但不能读取。其它的 location 属性和方法被禁止访问;
document.href 可以设置,但不能读取。其它的 document 属性和方法被禁止访问;
<iframe> 的 src 可以设置,但不能读取;
Javascript 相关文章推荐
慎用 somefunction.prototype 分析
Jun 02 Javascript
javascript中callee与caller的用法和应用场景
Dec 08 Javascript
jQuery 无刷新分页实例代码
Nov 12 Javascript
浅谈JavaScript中定义变量时有无var声明的区别
Aug 18 Javascript
JavaScript中的操作符类型转换示例总结
May 30 Javascript
JavaScript实现窗口抖动效果
Oct 19 Javascript
Vue.js创建Calendar日历效果
Nov 03 Javascript
利用JS实现文字的聚合动画效果
Jan 22 Javascript
使用vue-router完成简单导航功能【推荐】
Jun 28 Javascript
微信小程序实现授权登录
May 15 Javascript
Vuex模块化应用实践示例
Feb 03 Javascript
低门槛开发iOS、Android、小程序应用的前端框架详解
Oct 16 Javascript
JavaScript DOM 添加事件
Feb 14 #Javascript
CSS+Table图文混排中实现文本自适应图片宽度(超简单+跨所有浏览器)
Feb 14 #Javascript
JavaScript实现动态增加文件域表单
Feb 12 #Javascript
从JavaScript 到 JQuery (1)学习小结
Feb 12 #Javascript
谷歌浏览器 insertCell与appendChild的区别
Feb 12 #Javascript
js 判断 enter 事件
Feb 12 #Javascript
JavaScript 克隆数组最简单的方法
Feb 12 #Javascript
You might like
PHP中路径问题的解决方案
2006/10/09 PHP
深入php之规范编程命名小结
2013/05/15 PHP
apache中为php 设置虚拟目录
2014/12/17 PHP
php遍历树的常用方法汇总
2015/06/18 PHP
关于PHP开发的9条建议
2015/07/27 PHP
PHP+JS三级菜单联动菜单实现方法
2016/02/24 PHP
CI框架集成Smarty的方法分析
2016/05/17 PHP
PHP实现生成数据字典功能示例
2018/05/24 PHP
使用PHPUnit进行单元测试并生成代码覆盖率报告的方法
2019/03/08 PHP
php+mysql开发中的经验与常识小结
2019/03/25 PHP
PHP进阶学习之命名空间基本用法分析
2019/06/18 PHP
php进程(线程)通信基础之System V共享内存简单实例分析
2019/11/09 PHP
JS的数组的扩展实例代码
2008/07/09 Javascript
window.parent调用父框架时 ie跟火狐不兼容问题
2009/07/30 Javascript
Js 随机数产生6位数字
2010/05/13 Javascript
原生js实现shift/ctrl/alt按键的获取
2013/04/08 Javascript
js截取中英文字符串、标点符号无乱码示例解读
2014/04/17 Javascript
一个js过滤空格的小函数
2014/10/10 Javascript
JS修改iframe页面背景颜色的方法
2015/04/01 Javascript
轻松学习jQuery插件EasyUI EasyUI创建CRUD应用
2015/11/30 Javascript
js闭包学习心得总结
2018/04/17 Javascript
从源码里了解vue中的nextTick的使用
2018/11/22 Javascript
使vue实现jQuery调用的两种方法
2019/05/12 jQuery
JS闭包原理及其使用场景解析
2020/12/03 Javascript
python numpy 一维数组转变为多维数组的实例
2018/07/02 Python
Linux下python制作名片示例
2018/07/20 Python
Python 变量类型详解
2018/10/10 Python
python通过SSH登陆linux并操作的实现
2019/10/10 Python
pycharm如何实现跨目录调用文件
2020/02/28 Python
基于Pyinstaller打包Python程序并压缩文件大小
2020/05/28 Python
突袭HTML5之Javascript API扩展4—拖拽(Drag/Drop)概述
2013/01/31 HTML / CSS
英文自荐信常用句子
2014/03/26 职场文书
《海伦?凯勒》教学反思
2014/04/17 职场文书
老干部工作先进集体事迹材料
2014/05/21 职场文书
大学学雷锋活动总结
2014/06/26 职场文书
圣贤教育改变命运观后感
2015/06/16 职场文书