baidu的通行证处理都是在二级域名passport.baidu.com中处理的,但是baidu很多地方登录都好像是用ajax处理的,他是怎么做的呢?研究了一下,发现一个小技巧。
在http://zhidao.baidu.com/ 未登录用户回答问题时会用iframe调用http://zhidao.baidu.com/userlogin.html,userlogin.html 有下面的 javascript:
01 | <SCRIPT LANGUAGE= "JavaScript" > |
02 | document.domain= "baidu.com" ; |
04 | function G(id){ if ( typeof (id)== "string" ){ return document.getElementById(id);} return id;} |
05 | function showInfo(obj){ |
06 | if (obj.checked == true ){ |
07 | G( "memInfo" ).style.display= "block" ; |
09 | G( "memInfo" ).style.display= "none" ; |
12 | function request(id,url){ |
13 | oScript = document.getElementById(id); |
14 | var head = document.getElementsByTagName( "head" ).item(0); |
16 | head.removeChild(oScript); |
18 | oScript = document.createElement( "script" ); |
19 | oScript.setAttribute( "src" , url); |
20 | oScript.setAttribute( "id" ,id); |
21 | oScript.setAttribute( "type" , "text/javascript" ); |
22 | oScript.setAttribute( "language" , "javascript" ); |
23 | head.appendChild(oScript); |
26 | var loginTimer= null ; |
29 | function PSP_ik(isOk){ |
31 | G( "errorInfo" ).style.display= "none" ; |
33 | if (parent.loginSuccess){ |
35 | parent.loginSuccess(); |
44 | function loginFalse(){ |
46 | var err=G( "errorInfo" ); |
47 | err.innerHTML= "用户名或密码错误,请重新登录" ; |
48 | err.style.display= "block" ; |
49 | G( "username" ).focus(); |
55 | function onLoginFailed(){ |
56 | if (parent.onLoginFailed){ |
61 | doucment.login.submit(); |
65 | function loginTimeout(){ |
67 | var err=G( "errorInfo" ); |
68 | err.innerHTML= "操作超时,请重新登录" ; |
69 | err.style.display= "block" ; |
70 | G( "username" ).focus(); |
74 | var username=G( 'username' ).value; |
75 | var password=G( 'password' ).value; |
76 | var memPassport=G( 'memPassport' ).checked? "on" : "off" ; |
77 | if (username.length<=0||password.length<=0){G( "username" ).focus(); return false ;} |
80 | var login=request( "loginScript" ,url); |
81 | loginTimer = setTimeout(loginTimeout, 5000); |
84 | window.onload= function (){ |
85 | document.loginForm.username.focus(); |
86 | document.getElementById( "username" ).focus(); |
我们可以看到request方法处理异步请求使用动态往head中添加script而不是用xmlhttp发送get请求。妙就妙在这。我们知道调用javascript是没有域的限制的。当加载完成时一样会执行。
当然请求参数只能通过拼url的方式了。url通过服务器处理后直接输出loginFalse()或者PSP_ik();非常优雅的解决了跨域的问题。
这让我们想到了用iframe当ajax上传文件一样异曲同工。如果不需要服务器反馈,google的点击计数用new img().src=...;
当然baidu这段脚本中还有一些小的技巧也值得我们学习。