首页 > PHP资讯 > 工具库 > 微信二维码登录中的JS代码分析

微信二维码登录中的JS代码分析

工具库
在很多地方就是都出现了使用二维码登录,二维码付款,二维码账户等应用(这里的二维码种马,诈骗就不说了),二维码验证,多终端辅助授权应用开始多起来,这里先说下啥是二维码,其实二维码就是存了二进制数据的黑白http://www.php.cn/css/css-rwd-images.html" target="_blank">图片,当出现要求二维码登录的时候,服务器会生成一条临时的唯一的二维码信息,发送到客户端以二维码(图片)的形式写入到网页,然后你就会看到统一的四个方形的二维码,如果做的好这个二维码信息应该是有时效的,这里暂且不考虑这些,就简单的微信登录作为例子看看吧,

首先说下整个授权流程:

在客户端网页中会不断向服务器发送https连接,并且这里传输很少的数据之后就断开连接了,下面看下微信网页中这个login1c709c.js文件:

(function($, _aoWin) {_aoWin.QRLogin = {};  _aoWin.LoginLog = ""; var _sBaseHost = "",    _oLoginQrCodeImg = document.getElementById("loginQrCode"); if (document.domain == "qq.com") { _sBaseHost = "weixin.qq.com"; } else if(location.hostname.match(/(wechat.com)$/)){ _sBaseHost = "wechat.com"; }else{    _sBaseHost = "wechatapp.com";  }  var show_tip = 1, _sCurUUId, _oResetTimeout,    _aWebMMCallbacks = [],    _oDetactWebMMInterval = setInterval(function(){      if(_aoWin.WebMM){        clearInterval(_oDetactWebMMInterval);        var callback;        while(callback = _aWebMMCallbacks.shift()){          if(typeof(callback) != "function") continue;          callback();        }      }    }, 1000);function _logInPage(_asLog){    _aoWin.LoginLog = LoginLog + _asLog + "n";  }   function _afterLoadWebMMDo(callback){    if(!_aoWin.WebMM){      _aWebMMCallbacks.push(callback);    }else{      callback();    }  }   function _reportNow(text){    _logInPage(text);    _afterLoadWebMMDo(function(){      WebMM.ossLog({Text: text});      WebMM.flushOssLog();    });  }   var reLoadQRImgCount = 0,    loadQRCodeTime = 0,    loadQRImgSucc = function(){      clearInterval(loadQRImgWatchDog);      _logInPage("Load QRCode Success, time=" + (new Date().getTime() - loadQRCodeTime) + "ms, reload count: " + reLoadQRImgCount);    },    loadQRImgFail = function(img){      _reportNow("Load QRcode fail!" + status + ", src: " + img.src + ", time: " + (new Date().getTime() - loadQRCodeTime) + "ms");    },    loadQRImgWatchDog = null; function _loadQRImg(uuid) {    _poll(uuid);    _logInPage("Load QRCode Start");    loadQRCodeTime = new Date().getTime();     _oLoginQrCodeImg.onload = function(){      loadQRImgSucc();      _oLoginQrCodeImg.onload = null;    };    _oLoginQrCodeImg.onerror = function(){loadQRImgFail(this)};    _oLoginQrCodeImg.src = "https://login."+_sBaseHost+"/qrcode/"+uuid+"?t=webwx";     loadQRImgWatchDog = setInterval(function(){      if (reLoadQRImgCount >= 5) {        _reset();        return;      }      reLoadQRImgCount++;       var _img = new Image();      _img.onload = function () {        if(!_oLoginQrCodeImg.onload) return;         _oLoginQrCodeImg.onload = null;        _oLoginQrCodeImg.src = this.src;//replace        loadQRImgSucc();      };      _img.onerror = function(){loadQRImgFail(this)};      _img.src = _oLoginQrCodeImg.src + "&r=" + new Date().getTime();    }, 5000);  }   var _sSecondRequestTime = 0,    _nAjaxTimeout = 100 * 1000,    _nNewLoginFuncErrCount = 0; function _poll(_asUUID) { var _self = arguments.callee,      _nTime = 0; _sCurUUId = _asUUID;     _logInPage("_poll Request Start, time: " + new Date().getTime());    _nTime = new Date().getTime(); $.ajax({ type: "GET", url: "https://login." + _sBaseHost + "/cgi-bin/mmwebwx-bin/login?uuid=" + _asUUID + "&tip=" + show_tip, dataType: "script", cache: false, timeout: _nAjaxTimeout, success: function(data, textStatus, jqXHR) {      _logInPage("_poll Request Success, code: " + window.code + ", time: " + (new Date().getTime() - _nTime) + "ms");  switch (_aoWin.code) {  case 200:   _sSecondRequestTime = new Date().getTime() - _sSecondRequestTime;        _logInPage("Second Request Success, time: " + _sSecondRequestTime + "ms");  clearTimeout(_oResetTimeout);         var _fNewLoginFunc = function(){          $.ajax({            url: _aoWin.redirect_uri + "&fun=new",//new login page            type: "GET",            success:function(msg) {              _logInPage("new func reponse, reponseMsg: " + msg);              var code = msg.match(/《script》(.*)</script>/);              var skey=msg.match(/(.*)/);              if(code){                eval(code[1]);              }else{                $("#container").show();                $("#login_container").hide();              }              if(skey && skey[1]){               WebMM.model("account").setSkey(skey[1]);              }            },            error:function(jqXHR, textStatus, errorThrown){              _nNewLoginFuncErrCount++;              if(_nNewLoginFuncErrCount > 5){                if(confirm("Call new login page func error, refresh?")){location.reload()}                return;              }              _reportNow(_aoWin.redirect_uri + " New login page func error: " + textStatus +" retryCount:" + _nNewLoginFuncErrCount);              setTimeout(_fNewLoginFunc, 500);            }          });        };        _fNewLoginFunc();         _reportNow("/cgi-bin/mmwebwx-bin/login, Second Request Success, uuid: " + _asUUID + ", time: " + _sSecondRequestTime + "ms");  break;   case 201:        clearTimeout(_oResetTimeout);  show_tip = 0;  $('.errorMsg').hide();  $('.normlDesc').hide();  $('.successMsg').show();        _reportNow("/cgi-bin/mmwebwx-bin/login, First Request Success, uuid: " + _asUUID);        _reportNow("/cgi-bin/mmwebwx-bin/login, Second Request Start, uuid: " + _asUUID);         _sSecondRequestTime = new Date().getTime();         //_nAjaxTimeout = 5 * 1000;        _self(_asUUID);        break;   case 408:  setTimeout(function(){   _self(_asUUID);  }, 500);  break;   case 400:  case 500:        _reset();        _afterLoadWebMMDo(function(){   _aoWin.Log.d("500, Login Poll Svr Exception");  });  break;  } }, error: function(jqXHR, textStatus, errorThrown) {  if (textStatus == 'timeout') {        setTimeout(function(){          _self(_asUUID);        }, 500);  } else {        setTimeout(function(){          _self(_asUUID);        }, 5000);         _logInPage("_poll Request Error:" + textStatus);        _afterLoadWebMMDo(function(){          _aoWin.Log.e("Login Poll Error:" + textStatus);        });  } } }); }var getUUIDCount = 0,    _getUUIDWatchDog,    _bGetUUIDSuccess = false;//ajax successִ function _getUUID() {    getUUIDCount++;    var _self = arguments.callee,      _loadError = function(errorText){        _reportNow("Load UUID Error! ErrorText: " + errorText + " getUUIDCount=" + getUUIDCount);        if(getUUIDCount > 5){          if (confirm("Load uuid error. Refresh?")) {            location.reload();          }        }        setTimeout(function(){          _self();        }, 500);      };     clearTimeout(_getUUIDWatchDog);    _getUUIDWatchDog = setTimeout(function(){      if(!_aoWin.QRLogin.code){        _logInPage("GetUUID Timeout, WatchDog Run");        _self();      }    }, 10000);            $.ajax({                type: "GET",                url: "https://login." + _sBaseHost + "/jslogin?appid=wx782c26e4c19acffb&redirect_uri="+encodeURIComponent(location.protocol+"//"+location.host+"/cgi-bin/mmwebwx-bin/webwxnewloginpage")+"&fun=new&lang=" + document.lang,           dataType: "script",      cache: false,      success : function(){        clearTimeout(_getUUIDWatchDog);        if(_bGetUUIDSuccess) return;        if (_aoWin.QRLogin && _aoWin.QRLogin.code == 200) {          _logInPage("GetUUID Success, UUID=" + QRLogin.uuid);          _bGetUUIDSuccess = true;           clearTimeout(_oResetTimeout);          _oResetTimeout = setTimeout(function(){            location.reload();//Note: Don't run _reset(). If you run _reset(), there will may have many _poll request, as they get 408 return code          }, 5 * 60 *1000);//5 mins           _loadQRImg(QRLogin.uuid);        } else {          var QRLoginCode = (_aoWin.QRLogin && _aoWin.QRLogin.code) ? _aoWin.QRLogin.code : "None";          _logInPage("GetUUID Error, QRLogin.code=" + QRLoginCode);          _loadError("QRLogin.code= " + QRLoginCode);        }      },      error : function(xhr, textStatus, errorThrown){        _logInPage("GetUUID Error, textStatus=" + textStatus);        _loadError(textStatus);      }    }); }   function _reset(){    location.reload();  }  if ($("#login_container").is(":visible") ) {    _getUUID(); }    var _bHadLog = false; function _ossLog() { if (_bHadLog) return; _bHadLog = true; var _sUvid = document.cookie.match(new RegExp( "(^| )"+"webwxuvid"+"=([^;]*)(;|$)"));    if(!_sUvid || _sUvid.length < 3) return;    _sUvid = _sUvid[2]; (new Image()).src = "/cgi-bin/mmwebwx-bin/webwxstatreport?funkey=indexdemo&uvid="+_sUvid+"&uuid="+_sCurUUId; }   if($("img.guide").length > 0) { var _nTimer = 0,  _oGuide$ = $(".guide"),  _oGuideTrigger$ = $("#guideTrigger, #tipTrigger"),  _oMask$ = $(".mask");   function _back() {  _nTimer = setTimeout(function() {  _oMask$.stop().animate({opacity:0}, function(){$(".mask").hide()});  _oGuide$.stop().animate({marginLeft:"-120px",opacity:0}, "400", "swing",function(){   _oGuide$.hide();  });  }, 100); }  /*guide*/ _oGuide$.css({"left":"50%", "opacity":0}); _oGuideTrigger$.css({"backgroundColor":"white", "opacity":"0"}); _oGuideTrigger$.mouseover(function(){  clearTimeout(_nTimer);  _oMask$.show().stop().animate({"opacity":0.2});  _oGuide$.css("display", "block").stop().animate({marginLeft:"+168px", opacity:1}, 900, "swing", function() {  _oGuide$.animate({marginLeft:"+153px"}, 300);  });  _ossLog(); }).mouseout(_back);  _oGuide$.mouseover(function(){  clearTimeout(_nTimer); }).mouseout(_back); }})(jQuery, window);

细读js之后,你就会从网页客户端这边看到请求登录的一面,网页客户端每隔500毫秒就向服务器发起ssl请求,请求当前的二维码是否被其他客户端(手机)授权,如果返回结果是201,就是说明已经获取扫描二维码终端相同的账号登录授权,如果是其他情况就再隔500毫秒再循环发请求。这个过程会一直持续到二维码被扫描通过或者二维码超时(失效)为止。
其中使用的工具有: 抓包工具 Fidller ,Chrome F12开发人员工具,注意偶然的发现,微信的客户端有一个min-webmm1cba21.js ,其中清晰可见的XSS filter规范。

以上就是微信二维码登录中的JS代码分析的详细内容,更多请关注php中文网其它相关文章!

工具库

本文由欣才IT学院整理发布,未经许可,禁止转载。
支持1不支持0