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 相关文章推荐
JavaScript中几种常见排序算法小结
Feb 22 Javascript
setTimeout的延时为0时多个浏览器的区别
May 23 Javascript
ExtJS4中使用mixins实现多继承示例
Dec 03 Javascript
jquery获取对象的方法足以应付常见的各种类型的对象
May 14 Javascript
手机开发必备技巧:javascript及CSS功能代码分享
May 25 Javascript
JS实现点击复选框将按钮或文本框变为灰色不可用的方法
Aug 11 Javascript
原生js编写基于面向对象的分页组件
Dec 05 Javascript
微信小程序教程系列之设置标题栏和导航栏(7)
Jun 29 Javascript
从setTimeout看js函数执行过程
Dec 19 Javascript
解决微信授权成功后点击按返回键出现空白页和报错的问题
Jun 08 Javascript
vue实现给div绑定keyup的enter事件
Jul 31 Javascript
Vue3.0 手写放大镜效果
Jul 25 Vue.js
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中常用字符串处理代码片段整理
2011/11/07 PHP
PHP的运行机制与原理(底层)
2015/11/16 PHP
PHP使用xpath解析XML的方法详解
2017/05/20 PHP
php简单实现单态设计模式的方法分析
2017/07/28 PHP
ThinkPHP5.0框架验证码功能实现方法【基于第三方扩展包】
2019/03/11 PHP
ThinkPHP5&amp;5.1框架关联模型分页操作示例
2019/08/03 PHP
jquery 插件 web2.0分格的分页脚本,可用于ajax无刷新分页
2008/12/25 Javascript
js onpropertychange输入框 事件获取属性
2009/03/26 Javascript
你必须知道的JavaScript 中字符串连接的性能的一些问题
2013/05/07 Javascript
js模拟点击以提交表单为例兼容主流浏览器
2013/11/29 Javascript
jquery淡化版banner异步图片文字效果切换图片特效
2014/04/08 Javascript
JavaScript中reduce()方法的使用详解
2015/06/09 Javascript
jQuery针对input的class属性写了多个值情况下的选择方法
2016/06/03 Javascript
JS遍历页面所有对象属性及实现方法
2016/08/01 Javascript
jquery实现图片列表鼠标移入微动
2016/12/01 Javascript
vue跨域解决方法
2017/10/15 Javascript
详解最新vue-cli 2.9.1的webpack存在问题
2017/12/16 Javascript
详解微信JS-SDK选择图片遇到的坑
2018/08/15 Javascript
vue根据进入的路由进行原路返回的方法
2018/09/26 Javascript
Vue组件Draggable实现拖拽功能
2018/12/01 Javascript
详解vue-cli中使用rem,vue自适应
2019/05/06 Javascript
python脚本设置超时机制系统时间的方法
2016/02/21 Python
python中使用正则表达式的连接符示例代码
2017/10/10 Python
浅谈Python用QQ邮箱发送邮件时授权码的问题
2018/01/29 Python
Python 一句话生成字母表的方法
2019/01/02 Python
python实现词法分析器
2019/01/31 Python
python版DDOS攻击脚本
2019/06/12 Python
检测tensorflow是否使用gpu进行计算的方式
2020/02/03 Python
对tensorflow 中tile函数的使用详解
2020/02/07 Python
python GUI库图形界面开发之PyQt5输入对话框QInputDialog详细使用方法与实例
2020/02/27 Python
浅谈cv2.imread()和keras.preprocessing中的image.load_img()区别
2020/06/12 Python
Python的3种运行方式:命令行窗口、Python解释器、IDLE的实现
2020/10/10 Python
利用HTML5 Canvas API绘制矩形的超级攻略
2016/03/21 HTML / CSS
在职人员函授期间自我评价分享
2013/11/08 职场文书
党的群众路线教育实践活动党员个人整改措施
2014/10/27 职场文书
SpringBoot2零基础到精通之异常处理与web原生组件注入
2022/03/22 Java/Android