看看baidu是如何AJAX跨域的
最近做个人网站遇到AJAX跨子域名的问题。偶尔看到baidu的通行证处理都是在二级域名passport.baidu.com中处理的,
但是baidu很多地方登录都好像是用ajax处理的,他是怎么做的呢?研究了一下,发现一个小技巧。
不防让大家也借鉴一下。
在http://zhidao.baidu.com/ 未登录用户回答问题时会用iframe调用http://zhidao.baidu.com/userlogin.html
userlogin.html有下面的javascript
<
SCRIPTLANGUAGE
=
"
JavaScript
"
>
document.domain = " baidu.com " ;
<!--
function G(id) {if(typeof(id)=="string"){returndocument.getElementById(id);}returnid;}
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);
varhead=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);
returnoScript;
}
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;
varerr=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){
varerr=G("errorInfo");
err.innerHTML="操作超时,请重新登录";
err.style.display="block";
G("username").focus();
}
}
function userLogin() {
varusername=G('username').value;
varpassword=G('password').value;
varmemPassport=G('memPassport').checked?"on":"off";
if(username.length<=0||password.length<=0){G("username").focus();returnfalse;}
varurl='https://passport.baidu.com/?logt&tpl=ik&t=0&keyname=ik&mem_pass='+memPassport+'&username='+username+'&loginpass='+escape(password)+'&s='+(newDate()).getTime();
loginState=-1;
varlogin=request("loginScript",url);
loginTimer=setTimeout(loginTimeout,5000);
}
window.onload = function () {
document.loginForm.username.focus();
document.getElementById("username").focus();
}
// -->
< / SCRIPT>
我们可以看到
request方法处理异步请求使用动态往head中添加
script而不是用xmlhttp发送get请求。document.domain = " baidu.com " ;
<!--
function G(id) {if(typeof(id)=="string"){returndocument.getElementById(id);}returnid;}
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);
varhead=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);
returnoScript;
}
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;
varerr=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){
varerr=G("errorInfo");
err.innerHTML="操作超时,请重新登录";
err.style.display="block";
G("username").focus();
}
}
function userLogin() {
varusername=G('username').value;
varpassword=G('password').value;
varmemPassport=G('memPassport').checked?"on":"off";
if(username.length<=0||password.length<=0){G("username").focus();returnfalse;}
varurl='https://passport.baidu.com/?logt&tpl=ik&t=0&keyname=ik&mem_pass='+memPassport+'&username='+username+'&loginpass='+escape(password)+'&s='+(newDate()).getTime();
loginState=-1;
varlogin=request("loginScript",url);
loginTimer=setTimeout(loginTimeout,5000);
}
window.onload = function () {
document.loginForm.username.focus();
document.getElementById("username").focus();
}
// -->
< / SCRIPT>
妙就 妙在这。我们知道调用javascript是没有域的限制的。当加载完成时一样会执行。
当然请求参数只能通过拼url的方式了。
url通过服务器处理后直接输出 loginFalse()或者 PSP_ik(); 非常优雅的解决了跨域的问题。 这让我们想到了用iframe当ajax上传文件一样异曲同工。 如果不需要服务器反馈,google的点击计数用new img().src=...; 当然baidu这段脚本中还有一些小的技巧也值得我们学习。 原文链接:https://www.f2er.com/ajax/165422.html