新浪网站登录过程分析

  假前,寝室的猴哥跟我说帮忙写个新浪爱问的自动签到软件。结果一回来就感冒了,而且还是跨年的感冒。。。这中间什么都不想做,天天围在火旁边,吃东西、看电视。废话不多说了,开始正题。

  对于新浪的网站,只要你登录了其中一个,通过Cookie验证机制,你也就自动登录了其他网站。在试验登录新浪爱问的过程中,发现如果异地登录的话,会跳转到新浪会员登录页面。因此,本文分析了新浪会员登录页面的登录过程。

  分析过程中使用的工具:Mozilla Firefox浏览器以及相应插件FireBug、HttpFox、HttpRequester

  页面中登录窗口如下图所示:

  

  整个登录过程中的浏览器与服务器端的通信如下:

  1.输入完登录名后,输入焦点离开登录名输入框后,浏览器会向服务器发送请求:http://login.sina.com.cn/bindmail/checkmailuser.php?_r=1328093414030,请求方式为POST,POST的数据:name=pzxbc%40qq.com&type=json&ag=;返回数据:{"ret":"n","errcode":"limited"}
  POST数据解释:name:账户名,使用JavaScript函数encodeURIComponent进行URI编码。对应Python中相关函数urllib.quote();type:json;ag:空值
  返回数据解释:Request函数根据返回的值进行相关处理,具体请参看下面的源代码 。
  产生请求的原因: 在加载signin.php文件过程中执行了一下JS脚本,给登录名的输入框添加了一个Onblur事件函数。在输入焦点离开输入框后,调用了Onblur事件响应函数,Onblur函数调用了Request()函数,Request()函数通过调用ajaxCheck()产生上述请求。

bind(nameInput,"blur",function(){
nameTip.className = 'red_ero';
if(/^\s*$/.test(nameInput.value)) {
close('newDiv');
return;
}
if(/^\s*\d{1,9}\s*$/.test(nameInput.value)) {
//if (!submitFlag || $('ag').value == '')
openNewDiv('newDiv');
} else {
close('newDiv');
request();
}
});

function request(){
var ag = $('ag').value;
var url = "http://login.sina.com.cn/bindmail/checkmailuser.php";
ajaxCheck(location.protocol == "https:" ? url.replace(/^http:/, "https:") : url,"name="+encodeURIComponent(nameInput.value)+"&type=json&ag="+ag,function(res){
var data = eval('('+res+')');
if(data.ret == "y") {
nameTip.className = 'red_ero red_ero_fix';
nameTip.innerHTML = '<span class="yes"></span>为了您的帐号安全,请<a href="/bindmail/signin.php?username=' +nameInput.value+ '">绑定邮箱</a>';
} else if(data.ret == "n" && data.mail) {
nameTip.className = 'red_ero red_ero_fix';
if (data.errcode == 'not_verify') {
nameTip.innerHTML = '<span class="yes"></span>您的邮箱: '+data.mail+' 未验证,点此<a href="/bindmail/bindmail1.php?entry=sso&user='+data.mail+'">重发验证邮件</a>';
} else {
nameTip.innerHTML = '<span class="yes"></span>用您的邮箱'+data.mail+'也可以登录';
}
}
});
function ajaxCheck(url,data, callBack) {
var XHR;
var date = new Date();
try {
try{
XHR=new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){
try{
XHR=new XMLHttpRequest();
} catch (e){ }
}
XHR.open("POST",url+"?_r="+date.getTime());
XHR.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
XHR.onreadystatechange = function(){
if(XHR.readyState==4) {
if(XHR.status==200) {
if(callBack) callBack(XHR.responseText);
}
}
}
XHR.send(data);
}catch (e) {
alert(e.message);
}
}

  2.点击登录按钮后,产生请求:https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.17),POST数据:entry=account&gateway=1&from=&savestate=0&useticket=0&vsnf=1&su=cHp4YmMlNDBxcS5jb20%3D&service=account&sp=yourpassword&encoding=UTF-8&callback=parent.sinaSSOController.loginCallBack&returntype=IFRAME&setdomain=1;返回的数据:

<script type="text/javascript" language="javascript">
location.replace(
"http://login.sina.com.cn/crossdomain2.php?action=logincallback&retcode=4049&reason=%D3%C9%D3%DA%C4%FA%B5%C7%C2%BC%D2%EC%B3%A3%A3%AC%C7%EB%CC%EE%D0%B4%D1%E9%D6%A4%C2%EB&callback=parent.sinaSSOController.loginCallBack&setdomain=1");
</script>

  POST数据解释:su:帐号名,先通过JavaScript的encodeURIComponen()函数编码,然后再进行base64编码;sp:你的密码。
  产生请求的原因:signin.php文件中的OnReady()函数添加了表单的OnSumbit处理函数

$("vForm").onsubmit = function(){return login();};

  login()调用sinaSSOController.login()->sinaSSOController.loginMethodCheck()->sinaSSOController.loginByConfig() ->sinaSSOController.loginByIframe(),在loginByIframe()函数中新建了一个隐藏的loginForm,通过表单的Submit方法产生上述请求。
  3.步骤2请求后返回的内容,会是浏览器重定向到返回数据中所指示的网址:http://login.sina.com.cn/crossdomain2.php?action=logincallback&retcode=4049&reason=%D3%C9%D3%DA%C4%FA%B5%C7%C2%BC%D2%EC%B3%A3%A3%AC%C7%EB%CC%EE%D0%B4%D1%E9%D6%A4%C2%EB&callback=parent.sinaSSOController.loginCallBack&setdomain=1,所以会产生一个GET请求。如果返回数据中retcode值为0,表示登录成功。

<script>
if(1) document.domain = "sina.com.cn";
parent.sinaSSOController.setCrossDomainUrlList({
"retcode":0,"arrURL":["http:\/\/weibo.com\/sso\/crosdom?action=login","http:\/\/kandian.com\/logon\/do_crossdomain.php?action=login","http:\/\/login.t.cn\/sinaurl\/sso.json?action=login&uid=1830667973"]});parent.sinaSSOController.loginCallBack({"retcode":"0","uid":"1830667973"});;
</script>

  返回以下两种内容表示,登录不成功

<script>
//情况1:异地登录,需要重新输入验证码
if(1) document.domain = "sina.com.cn";
parent.sinaSSOController.loginCallBack({
"retcode":"4049","reason":"\u7531\u4e8e\u60a8\u767b\u5f55\u5f02\u5e38\uff0c\u8bf7\u586b\u5199\u9a8c\u8bc1\u7801"});;
</script>

<script>
//情况2:验证码输入错误
if(1) document.domain = "sina.com.cn";
parent.sinaSSOController.loginCallBack({
"retcode":"2070","reason":"\u8f93\u5165\u7684\u9a8c\u8bc1\u7801\u4e0d\u6b63\u786e"});;
</script>

  4.然后交叉登录新浪的其他网站,分别请求一下三个地址:
  http://weibo.com/sso/crosdom?action=login&callback=sinaSSOController.doCrossDomainCallBack&scriptId=ssoscript0&client=ssologin.js(v1.3.17)&_=1328256974181;
  http://kandian.com/logon/do_crossdomain.php?action=login&callback=sinaSSOController.doCrossDomainCallBack&scriptId=ssoscript1&client=ssologin.js(v1.3.17)&_=1328256974192;
  http://login.t.cn/sinaurl/sso.json?action=login&uid=1830667973&callback=sinaSSOController.doCrossDomainCallBack&scriptId=ssoscript2&client=ssologin.js(v1.3.17)&_=1328256974211
  其中_=后面的是JavaScript中time()函数的返回值,uid为步骤3中的返回值。

  5.登录成功后,调用signinconfig.js中的customLoginCallBack()函数,customLoginCallBack()函数产生GET请求:http://login.sina.com.cn/,然后转向:http://login.sina.com.cn/member/app.php?entry=sso&act=my,最后转向:http://login.sina.com.cn/member/my.php?entry=sso,至此整个登录过程完成了。

var url = getReturnUrl(); //返回URL:http://login.sina.com.cn/
if (this.crossDomain) {
window.location.replace(url);
return true;




   

 

   

posted @ 2012-02-03 17:00  pzxbc  阅读(8405)  评论(0编辑  收藏  举报