参考文档:http://hi.baidu.com/xusx/blog/item/d7cda3c34d86a957b219a8d1.html
在实际的应用中,ajax对不同域下内容的访问有非常严格的限制,以下情况不允许访问:
- 不同域,包括二级域名。
- 不同端口。
- 不同协议。
通常的解决方案有以下几种:
script块
/*******
*jsLoader
*
*/
var Transfer={}
Transfer.Base = function() {}
Transfer.Base.prototype = {
setOptions: function(options) {
if(typeof options!="object"){options={};}
this.options = {
bCache:options.bCache||false,
id:options.id||"scriptTemp",
onfailure:options.onfailure||function(){},
oncomplate:options.oncomplate||function(){}
}
}
}
/**
new Transfer.Request(url,{oncomplate:'',id:''})
*/
Transfer.Request=Class.create();
Transfer.Request.prototype=Object.extend(new Transfer.Base(),{
initialize: function(url, options) {
this.setOptions(options);
this.request(url);
},
request:function(url){
this.url=url;
this.bCache=this.options.bCache;
this.id=this.options.id;
this.oncomplate=this.options.oncomplate;
this.onfailure=this.options.onfailure;
this.symbol="?";
if(this.url.indexOf("?")!="-1")this.symbol="&";
var head=document.getElementsByTagName("head")[0];
var sT = $(this.id);
if(sT&&sT.src&&sT.src==this.url){
this.oncomplate();
return;
}
if (sT) {sT.parentNode.removeChild(sT);}
var s = document.createElement("script");
head.appendChild(s);
s.setAttribute("language", "javascript");
s.setAttribute("type", "text/javascript");
s.setAttribute("id", this.id);
s.setAttribute("src", (this.bCache && this.bCache == true) ? this.url + this.symbol + Math.random() : this.url);
var self=this;
s.onload=s.onreadystatechange=function()
{
if (typeof ActiveXObject!="undefined") {
if(s.readyState&&s.readyState=="loaded")self.oncomplate();
if(s.readyState&&s.readyState=="complete")return;
}else{
self.oncomplate();
}
}
s.onerror=function(){ //ie not work
if(s&&s.parentNode)s.parentNode.removeChild(s);
self.onfailure();
throw new Error("connect faild,please try later;");
}
}
});
/****jsLoader end****/
document.domain
当主域、协议、端口相同时,通过设置页面的document.domain主域,Javascript可以在不同的子域名间访问控制,比如通过设置 document.domain=’dancewithnet.com’,http://dancewithnet.com和http: //lab.dancewithnet.com页面可互访,这个特性也提供了此情况下不同子域名下的XMLHTTPRequest相互访问的解决方案。
对于主域、协议、端口相同时的Ajax跨域问题,很早就有设置document.domain来解决的说法,但一直没有看到具体的成功应用,这几天尝试了一下,其原理就是,利用一个隐藏的iframe引入所跨另一子域的页面作为代理,通过Javascript来控制iframe引入的另一子域的 XMLHTTPRequest来进行数据获取。
例子:
<!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>用document.domain解决Ajax跨域</title></head> <body><iframe src="http://lab.dancewithnet.com/2007/07/solve-cross-domain-ajax-with-document-domain/proxy.html" id="proxy"></iframe>
<script type="text/javascript" src="http://dancewithnet.com/lab/yui/yahoo-dom-event.js"></script><script type="text/javascript" src="http://dancewithnet.com/lab/yui/connection.js"></script>
<script type="text/javascript">//<![CDATA[document.domain = 'dancewithnet.com';var $D = YAHOO.util.Dom;var $ = $D.get;var $E = YAHOO.util.Event;var $C = YAHOO.util.Connect;$E.on('btn1','click',getContent1);
var getContent2 = function(){ var sUrl = 'http://lab.dancewithnet.com/eg.txt'; var proxy = $('proxy').contentWindow; var proxy$C = proxy.YAHOO.util.Connect; var request = proxy$C.asyncRequest('GET',sUrl,{ success:function(o){ $('content2').innerHTML = o.responseText; }, failure:function(){} });}$E.on('btn2','click',getContent2);//]]></script> </body> </html>
后台代理方式
对于不同主域/不同协议/不同端口下的Ajax访问需要通过后台的代理来实现,更多细节可以看看Use a Web Proxy for Cross-Domain XMLHttpRequest Calls和Fixing AJAX: XMLHttpRequest Considered Harmful。”
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
转:
好久没写文章了,不过中午看了一篇关于“用document.domain解决Ajax跨子域”的文章后,心里的一个结差不多解开了,索性也就此总结一下。
以前做网站的时候,遇到跨站(域)调用文章的问题,那时候没想到什么好方法,一般用iframe、Javascript文件调用或手动添加l链接,由于这些跨站调用的内容不多又不经常,所以也没大放在心里。尽管碰到网上不少的“小偷程序”和“采集程序”,但也没去多想什么。
现在,大量跨站(域)调用内容的情形总算遇到了,得想个高明些的办法,毕竟时代不同了。
于是到书上或google上学xml,xmlhttp,ajax,由于时间有限,囫囵吞枣,几经周折,最终发现实现的方法并不高明,效率当然也不高。
今天中午吃晚饭,上蓝色理想,没想碰到“随网之舞”(http://dancewithnet.com/)里的一篇“用document.domain解决Ajax跨子域”,顺便摘抄如下:
“因为浏览器的安全策略,浏览器不允许不同域(比如:dancewithnet.com和lab.dancewithnet.com)、不同协议(比如:http://dancewithnet.com和https://dancewithnet.com)、不同端口(比如:http:dancewithnet.com和http://dancewithnet.com:8080)下的页面通过XMLHTTPRequest相互访问,这个问题同样影响着不同页面的Javascript的相互调用和控制,但是当主域、协议、端口相同时,通过设置页面的document.domain主域,Javascript可以在不同的子域名间访问控制,比如通过设置document.domain=’dancewithnet.com’,http://dancewithnet.com和http://lab.dancewithnet.com页面可互访,这个特性也提供了此情况下不同子域名下的XMLHTTPRequest相互访问的解决方案。
“对于主域、协议、端口相同时的Ajax跨域问题,很早就有设置document.domain来解决的说法,但一直没有看到具体的成功应用,这几天尝试了一下,其原理就是,利用一个隐藏的iframe引入所跨另一子域的页面作为代理,通过Javascript来控制iframe引入的另一子域的XMLHTTPRequest来进行数据获取。请看实例>>
“对于不同主域/不同协议/不同端口下的Ajax访问需要通过后台的代理来实现,更多细节可以看看Use a Web Proxy for Cross-Domain XMLHttpRequest Calls和Fixing AJAX: XMLHttpRequest Considered Harmful。”
我想这是一个不错的想法,所以也想尝试一下,至于具体过程,等到有空再写吧。
第一种方法的例子:
var Transfer={};
Transfer.Base = function() {};
Transfer.Base.prototype = {
setOptions: function(options) {
if(typeof options!="object"){
options={};
};
this.options = {
bCache:options.bCache||false,
id:options.id||"scriptTemp",
onfailure:options.onfailure||function(){},
oncomplate:options.oncomplate||function(){}
}
}
};
//propotype.js
var Class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
};
Object.extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
};
Transfer.Request=Class.create();
Transfer.Request.prototype=Object.extend(new Transfer.Base(),{
initialize: function(url, options) {
this.setOptions(options);
this.request(url);
},
request:function(url){
this.url=url;
this.bCache=this.options.bCache;
this.id=this.options.id;
//传入的方法名
this.oncomplate=this.options.oncomplate;
this.onfailure=this.options.onfailure;
this.symbol="?";
if(this.url.indexOf("?")!="-1")this.symbol="&";
var head=document.getElementsByTagName("head")[0];
var sT = document.getElementById(this.id);
if(sT&&sT.src&&sT.src==this.url){
this.oncomplate();
return;
}
if (sT) {
sT.parentNode.removeChild(sT);
}
//构建<script id="传入id" type="text/javascript" src="传入的url">
var s = document.createElement("script");
head.appendChild(s);
s.setAttribute("language", "javascript");
s.setAttribute("type", "text/javascript");
s.setAttribute("id", this.id);
s.setAttribute("src", (this.bCache && this.bCache == true) ? this.url + this.symbol + Math.random() : this.url);
var self=this;
s.onload=s.onreadystatechange=function()
{
if (typeof ActiveXObject!="undefined") {
//加载成功启动 传入的方法 被加载的对象
if(s.readyState&&s.readyState=="loaded")self.oncomplate();//调用函数
if(s.readyState&&s.readyState=="complete")return;
}else{
self.oncomplate();
}
}
s.onerror=function(){ //ie not work
s.parentNode.removeChild(s);
self.onfailure();
throw new Error("some error occurd,please try again later");
}
}
});
页面调用:
function transfers(){
if('<%=searchType%>'=='行车路线'){
new Transfer.Request("&destLatLon=< DLatAndDLon>http://mapx.mapbar.com/json/getDriveByNid.jsp?origLatLon=<%=DLatAndDLon1%>&destLatLon=<%=DLatAndDLon2%>",{
oncomplate:getDrive,
id:'drive'
});
}else{
new Transfer.Request("&origLatLon=< DLatAndDLon>&destLatLon=<%=DLatAndDLon2%">http://mapx.mapbar.com/json/getBusByNid.jsp?city=<%=strCity%>&origLatLon=<%=DLatAndDLon1%>&destLatLon=<%=DLatAndDLon2%
>",{oncomplate:getBus,
id:'busResult'
});
}
}
function getDrive(){
alert(drive);//drive为调用另一个域返回的对象
var routes="共"+drive.routes.count+"个步骤";
}