看看baidu是如何AJAX跨域的

5iasp
博客专家认证
2008-12-24 09:32:27
看看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跨域的时候花儿也谢了
...全文
22237 243 打赏 收藏 转发到动态 举报
写回复
用AI写文章
243 条回复
切换为时间正序
请发表友善的回复…
发表回复
wumingmao1990 2012-08-17
  • 打赏
  • 举报
回复
没看懂。。
似梦飞花 2012-06-26
  • 打赏
  • 举报
回复
留个爪印
david522 2012-05-16
  • 打赏
  • 举报
回复
学习了
hzhtc_555 2012-02-23
  • 打赏
  • 举报
回复
学习了,感谢高手的教程,谢谢!
鸭不梨儿 2012-02-23
  • 打赏
  • 举报
回复
标记,以后慢慢看。
asd5640252 2011-12-21
  • 打赏
  • 举报
回复
mark
ym231074255 2011-12-01
  • 打赏
  • 举报
回复
看不懂。。MARK
tylrr123 2011-07-24
  • 打赏
  • 举报
回复
收藏了 谢谢
OPPPPOP 2011-07-04
  • 打赏
  • 举报
回复
那我觉得用script 标签 来代替Ajax非常好 都是script的事 多好的 非要扯过来个 xmlHttprequest 返回值还要 script来解析 麻烦
wujj_wtj 2011-07-04
  • 打赏
  • 举报
回复
学习了
lucifer 2011-05-12
  • 打赏
  • 举报
回复
mark一下
鱼呗 2010-12-17
  • 打赏
  • 举报
回复
Mark
andyniuandyniu 2010-12-12
  • 打赏
  • 举报
回复
学习mark
baimin5211314 2010-12-08
  • 打赏
  • 举报
回复
膜拜,楼主中......
edgesun 2010-11-27
  • 打赏
  • 举报
回复
大家都知道ajax不能跨域,还在拼命的找跨域方法,俺也是来取经的。学习了
myqq155120699 2010-11-27
  • 打赏
  • 举报
回复
mark

以后再看。
itaoo 2010-10-05
  • 打赏
  • 举报
回复
mark
jblxmn 2010-09-28
  • 打赏
  • 举报
回复
挖份 MARK下
cph1737 2010-09-26
  • 打赏
  • 举报
回复
学习了,非常感谢
黄瓜 2010-09-26
  • 打赏
  • 举报
回复

竟然没看懂~~
加载更多回复(223)
jQuery.ajax( url, [ settings ] ) 返回: jqXHR 执行一个异步的HTTP(Ajax)的请求。 version added: 1.5jQuery.ajax( url, [ settings ] ) url一个用来包含发送请求的URL字符串。 settings一个以"{键:值}"组成的AJAX 请求设置。所有选项都是可选的。可以使用$.ajaxSetup()设置任何默认参数。看jQuery.ajax( settings )下所有设置的完整列表。 version added: 1.0jQuery.ajax( settings ) settings一个以"{键:值}"组成的AJAX 请求设置。所有选项都是可选的。可以使用$.ajaxSetup()设置任何默认参数。 acceptsMap 默认: 取决于数据类型 内容类型发送请求头,告诉服务器什么样的响应会接受返回。如果accepts设置需要修改,推荐在$.ajaxSetup()方法中做一次。 asyncBoolean 默认: true 默认设置下,所有请求均为异步请求(也就是说这是默认设置为true)。如果需要发送同步请求,请将此选项设置为 false。跨域请求和dataType: "jsonp"请求不支持同步操作。注意,同步请求将锁住浏览器,用户其它操作必须等待请求完成才可以执行。 beforeSend(jqXHR, settings)Function 发送请求前可修改 jqXHR(在jQuery 1.4.x的中,XMLHttpRequest) 对象的函数,如添加自定义 HTTP 头等。该jqXHR和设置作为参数传递的。这是一个Ajax事件 。beforeSend行数返回的false将取消该请求。在jQuery 1.5, beforeSend选项将被访问,不管请求的类型。 cacheBoolean 默认: true, dataType为"script"和"jsonp"时默认为false 如果设置为 false ,浏览器将不缓存此页面。 complete(jqXHR, textStatus)Function, Array 请求完成后回调函数 (请求成功或失败之后均调用)。这个回调函数得到2个参数: jqXHR (in jQuery 1.4.x, XMLHTTPRequest) 对象和一个描述成功请求类型的字符串("success", "notmodified", "error","timeout", or "parsererror") 。在jQuery 1.5, complete设置可以接受一个函数的数组。每个函数将被依次调用。这是一个Ajax事件 。 contents(added 1.5)Map 一个以"{字符串:正则表达式}"配对的对象,用来确定jQuery将如何解析响应,给定其内容类型。 contentTypeString 默认: 'application/x-www-form-urlencoded' 发送信息至服务器时内容编码类型。默认值是"application/x-www-form-urlencoded",适合大多数情况。如果你明确地传递了一个content-type给 $.ajax() 那么他必定会发送给服务器(即使没有数据要发送)。数据将总是使用UTF-8字符集传递给服务器;你必须译码这适当的在服务器端。 contextObject 这个对象用于设置Ajax相关回调函数的上下文。也就是说,让回调函数内this指向这个对象(如果不设定这个参数,那么this就指向调用本次AJAX请求时传递的options参数)。比如指定一个DOM元素作为context参数,这样就设置了success回调函数的上下文为这个DOM元素。就像这样: $.ajax({ url: "test.html", context: document.body, success: function(){ $(this).addClass("done"); } });

87,914

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧