`
dengminhui
  • 浏览: 163981 次
  • 来自: ...
社区版块
存档分类
最新评论

如何解决跨域问题

阅读更多

跨域问题总是很难缠,很多时候开发人员都是不自觉间就遇到了跨域,在此晒晒我的解决之道。

 

1 避免跨域

在最近一个需求中,有一个网页会出现在两个域名下,开始完全没想到这个问题,导致跨域问题产生,出问题代码如下

 

 

<form id="form1" method="post" action="http://www.anotherDomain.com/a.htm?_input_charset=UTF-8">
       <input type="hidden" name="action" value="SomeAction"/>
       <input type="hidden" name="event_submit_do_something" value="true"/>
           ......
</form>

<script language="javascript">

myAjax = function(){
         myhandle = function (hr){
        		alert(hr.responseText);
				
        }
           YAHOO.util.Connect.asyncRequest(
					'POST',
					FD.common.getFormAction('form1'),
					{ 
					success : myhandle, 
					failure : myhandle, 
					timeout : 10000 
					}, 
					FD.common.formSerialize('form1') + '&param1='+document.getElementById('param1').value
	  );
}
</script>

 

修改方案很简单,采用相对路径

<form id="form1" method="post" action="?_input_charset=UTF-8">

 这是最简单的办法,因为本身都是一个页面。在公司框架中,这两种写法,程序最终执行的都是SomeAction中doSomething函数,但是程序发送的请求则有所不同,前者发送到了www.anotherDomain下,后者则在当前的域名下,所以跨域问题也就不存在了。

 

 

2 采用jsonp方式

如果你还没听过什么是jsonp,可以先看看http://baike.baidu.com/view/2131174.htm?fr=ala0_1

简单说来,就是采用json方式返回数据,和普通json不同的就是将地址写在script的src属性里欺骗浏览器

为了从另外一个域名下的test.html页面取得一个json数据

var ajaxResult={"count":1};
 

可以在页面的头部添加这样一句即可

 

<script src="http://www.anotherdomian.com/test.html?param1=$param1" type="text/javascript"></script>

其中的$param1是由服务器的程序生成,所以每次页面打开后其实$param1是不可变的。就是采用这种方式,页面打开后就可以直接使用ajaxResult这个js的变量了,

 

3 jsonp方式改进

前一种方法如果说还有什么不好的,那可能就是不够动态吧,下面对第2种方式进行改进。

在http://zhidao.baidu.com/ 未登录用户回答问题时会用iframe调用http://zhidao.baidu.com/userlogin.html
userlogin.html有下面的javascript

 

<SCRIPT LANGUAGE="JavaScript">
document.domain="baidu.com";
<!--
function G(id){if(typeof(id)=="string"){return document.getElementById(id);}return id;}
function showInfo(obj){
  if(obj.checked == true){
  G("memInfo").style.display="block";
  }else{
  G("memInfo").style.display="none";
  }
}
function request(id,url){
  oScript = document.getElementById(id);
  var head = document.getElementsByTagName("head").item(0);
  if (oScript) {
  head.removeChild(oScript);
  }
  oScript = document.createElement("script");
  oScript.setAttribute("src", url);
  oScript.setAttribute("id",id);
  oScript.setAttribute("type","text/javascript");
  oScript.setAttribute("language","javascript");
  head.appendChild(oScript);
  return oScript;
}
var loginTimer=null;
var loginState=-1;
var tryTime=0;
function PSP_ik(isOk){
  if(isOk==0){
  G("errorInfo").style.display="none";
  loginState=1;
  if(parent.loginSuccess){
  parent.Pop.hide();
  parent.loginSuccess();
  }
  }
  else
  {
  loginFalse();
  }
}

function loginFalse(){
  loginState=0;
  var err=G("errorInfo");
  err.innerHTML="用户名或密码错误,请重新登录";
  err.style.display="block";
  G("username").focus();
  tryTime++;
  if(tryTime>1){
  onLoginFailed();
  }
}
function onLoginFailed(){
  if(parent.onLoginFailed){
  parent.Pop.hide();
  parent.loginFailed();
  }else{
  document.login.u.value=escape("http://zhidao.baidu.com/q"+parent.location.search);
  doucment.login.submit();
  }
   
}
function loginTimeout(){
  if(loginState==-1){
  var err=G("errorInfo");
  err.innerHTML="操作超时,请重新登录";
  err.style.display="block";
  G("username").focus();
  }
}
function userLogin(){
  var username=G('username').value;
  var password=G('password').value;
  var memPassport=G('memPassport').checked?"on":"off";
  if(username.length<=0||password.length<=0){G("username").focus();return false;}
  var url = 'https://passport.baidu.com/?logt&tpl=ik&t=0&keyname=ik&mem_pass='+memPassport+'&username='+username + '&loginpass=' +escape(password)+ '&s=' + (new Date()).getTime();
  loginState=-1;
  var login=request("loginScript",url);
  loginTimer = setTimeout(loginTimeout, 5000);

}
window.onload=function(){
  document.loginForm.username.focus();  
  document.getElementById("username").focus(); 
}
//-->
</SCRIPT>
 

 

request方法处理异步请求使用动态往head中添加script而不是用xmlhttp发送get请求。妙就妙在这。我们知道调用javascript是没有域的限制的。当加载完成时一样会执行。

 

4 通过服务器绕过跨域

将原有的ajax请求,发送到本域名下后台程序,通过后台程序去取得另外一个域名下页面的内容,由于服务器程序不存在跨域的问题,当它得到数据后,再以ajax.responseText返回给原页面,则跨域也可得到解决。


 

参考文档:

http://baike.baidu.com/view/2131174.htm?fr=ala0_1

http://topic.csdn.net/u/20081224/09/26aff992-d0ba-4f6f-a023-e0e96ecbe1fc.html

 

 

3
2
分享到:
评论
2 楼 libmw 2010-05-16  
上个月腾讯面试我,问我JSONP是啥东西,我说没通过,结果直接就被鄙视了~楼主帖子咋不早发啊
1 楼 vb2005xu 2010-05-13  
_dataParser: function(data){ // 从对象生成查询格式的字符串
if (!xu.verify._obj(data)) return null;
var param_key = function(key,pkey){
if(!pkey)return key ;
return pkey + '[' + key + ']' ;
};
var obj2qparams = function(obj,pkey){
var qstr = '' ,pkey = pkey || null ;
for(var p in obj){
if (obj.hasOwnProperty(p) && xu.verify._str(p)){
if (xu.verify._obj(obj[p])){
qstr += obj2qparams(obj[p],param_key(p,pkey));
}else
qstr += param_key(p,pkey) + '=' + obj[p] + '&' ;
}
}
return qstr ;
};
// demo
// data['user'] = {name:'se',ps:123,role:{name:'admin',group:{name:'backup'}}};
return obj2qparams(data).replace(/&$/,'');
}

相关推荐

Global site tag (gtag.js) - Google Analytics