3kk小游戏

看看baidu是如何AJAX跨域的

最近做个人网站遇到AJAX跨子域名的问题。

偶尔看到baidu的通行证处理都是在二级域名passport.baidu.com中处理的,
但是baidu很多地方登录都好像是用ajax处理的,他是怎么做的呢?研究了一下,发现一个小技巧。
不防让大家也借鉴一下。
在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是没有域的限制的。当加载完成时一样会执行。

当然请求参数只能通过拼url的方式了。
url通过服务器处理后直接输出loginFalse()或者PSP_ik();
非常优雅的解决了跨域的问题。

这让我们想到了用iframe当ajax上传文件一样异曲同工。
如果不需要服务器反馈,google的点击计数用new img().src=...;

当然baidu这段脚本中还有一些小的技巧也值得我们学习。

总结一句 活学活用 不要钻牛角尖,要不等我们解决ajax跨域的时候花儿也谢了


posted on 2008-07-16 08:40  passer.net  阅读(3111)  评论(2编辑  收藏  举报

导航