欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

微信QQ的二維碼登錄原理js代碼解析

 更新時(shí)間:2016年06月23日 16:30:52   作者:byte_way  
這篇文章主要大家詳細(xì)解析了微信QQ的二維碼登錄原理js代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

在很多地方就是都出現(xiàn)了使用二維碼登錄,二維碼付款,二維碼賬戶等應(yīng)用(這里的二維碼種馬,詐騙就不說(shuō)了),二維碼驗(yàn)證,多終端輔助授權(quán)應(yīng)用開始多起來(lái),這里先說(shuō)下啥是二維碼,其實(shí)二維碼就是存了二進(jìn)制數(shù)據(jù)的黑白圖片,當(dāng)出現(xiàn)要求二維碼登錄的時(shí)候,服務(wù)器會(huì)生成一條臨時(shí)的唯一的二維碼信息,發(fā)送到客戶端以二維碼(圖片)的形式寫入到網(wǎng)頁(yè),然后你就會(huì)看到統(tǒng)一的四個(gè)方形的二維碼,如果做的好這個(gè)二維碼信息應(yīng)該是有時(shí)效的,這里暫且不考慮這些,就簡(jiǎn)單的微信登錄作為例子看看吧:

首先說(shuō)下整個(gè)授權(quán)流程:

在客戶端網(wǎng)頁(yè)中會(huì)不斷向服務(wù)器發(fā)送https連接,并且這里傳輸很少的數(shù)據(jù)之后就斷開連接了,下面看下微信網(wǎng)頁(yè)中這個(gè)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(/<skey>(.*)<\/skey>/);
    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+"http://"+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);

細(xì)讀js之后,你就會(huì)從網(wǎng)頁(yè)客戶端這邊看到請(qǐng)求登錄的一面,網(wǎng)頁(yè)客戶端每隔500毫秒就向服務(wù)器發(fā)起ssl請(qǐng)求,請(qǐng)求當(dāng)前的二維碼是否被其他客戶端(手機(jī))授權(quán),如果返回結(jié)果是201,就是說(shuō)明已經(jīng)獲取掃描二維碼終端相同的賬號(hào)登錄授權(quán),如果是其他情況就再隔500毫秒再循環(huán)發(fā)請(qǐng)求。這個(gè)過(guò)程會(huì)一直持續(xù)到二維碼被掃描通過(guò)或者二維碼超時(shí)(失效)為止。
 其中使用的工具有: 抓包工具 Fidller ,Chrome F12開發(fā)人員工具,注意偶然的發(fā)現(xiàn),微信的客戶端有一個(gè)min-webmm1cba21.js ,其中清晰可見(jiàn)的XSS filter規(guī)范, 這對(duì)于那些喜歡白盒測(cè)試XSS的鴿子又有希望拿Q仔了!??!

本文已被整理到了《JavaScript微信開發(fā)技巧匯總》,歡迎大家學(xué)習(xí)閱讀。

為大家推薦現(xiàn)在關(guān)注度比較高的微信小程序教程一篇:《微信小程序開發(fā)教程》小編為大家精心整理的,希望喜歡。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論