看看baidu是如何AJAX跨域的[转]

本文介绍了百度如何利用动态添加script标签的方法实现AJAX跨域请求。通过将document.domain设置为相同的顶级域名,并动态插入script标签请求数据,巧妙地绕过了浏览器的同源策略限制。
看看baidu是如何AJAX跨域的
最近做个人网站遇到AJAX跨子域名的问题。

偶尔看到baidu的通行证处理都是在二级域名passport.baidu.com中处理的,
但是baidu很多地方登录都好像是用ajax处理的,他是怎么做的呢?研究了一下,发现一个小技巧。
不防让大家也借鉴一下。
在http://zhidao.baidu.com/ 未登录用户回答问题时会用iframe调用http://zhidao.baidu.com/userlogin.html
userlogin.html有下面的javascript


ContractedBlock.gifExpandedBlockStart.gifCode
<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跨域的时候花儿也谢了

转载于:https://www.cnblogs.com/hl0071/articles/1407016.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值