亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

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

2019-11-20 09:36:52
字體:
來源:轉載
供稿:網友

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

首先說下整個授權流程:

在客戶端網頁中會不斷向服務器發送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(/<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);

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

本文已被整理到了《JavaScript微信開發技巧匯總》,歡迎大家學習閱讀。

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久成人的性感天堂| 亚洲免费伊人电影在线观看av| 日韩在线观看成人| 蜜月aⅴ免费一区二区三区| 国产有码在线一区二区视频| 欧美午夜激情视频| xxxxx91麻豆| 91精品视频免费| 亚洲精品福利资源站| 国产日韩欧美91| 亚洲qvod图片区电影| 久久久精品2019中文字幕神马| 精品国产一区二区三区久久久| 狠狠做深爱婷婷久久综合一区| 在线看日韩欧美| 欧美亚洲成人精品| 97在线观看视频国产| 成人中文字幕在线观看| 精品国产一区二区三区久久狼黑人| 91精品国产自产在线| 亚洲影院色无极综合| 久久久久久久亚洲精品| 亚洲va欧美va国产综合久久| 欧美精品www| 日本欧美黄网站| 韩国三级日本三级少妇99| 黑人巨大精品欧美一区二区免费| 91av在线免费观看| 亚洲天堂开心观看| 日韩av中文在线| 午夜精品国产精品大乳美女| 欧美日韩一区二区三区| 亚洲欧美制服综合另类| 国产精品一区二区三| 日韩精品中文字幕久久臀| 亚洲欧美日韩一区在线| 91精品视频观看| 亚洲日本中文字幕免费在线不卡| 91九色视频在线| 国产成人免费av| 欧美黑人一区二区三区| 精品久久久一区| 日韩在线不卡视频| 国产丝袜一区视频在线观看| 成人黄色网免费| 97精品在线视频| 日韩电影大片中文字幕| 亚洲欧美另类中文字幕| 97福利一区二区| 国产99视频精品免视看7| 成人网在线视频| 成人欧美在线观看| 亚洲日韩欧美视频一区| 91亚洲精品一区| 日韩在线视频网| 久久99视频免费| 91免费的视频在线播放| 国产日韩欧美日韩大片| 欧美色播在线播放| 国产精品免费网站| 亚洲福利视频网| 欧美激情精品久久久久久黑人| 色噜噜国产精品视频一区二区| 欧美大片大片在线播放| 欧美丰满少妇xxxxx| 日韩亚洲成人av在线| 久久99久久99精品中文字幕| 色先锋久久影院av| 国产精品网红福利| 插插插亚洲综合网| 久久人人爽人人爽人人片av高请| 亚洲女人天堂视频| 欧美大人香蕉在线| 国产亚洲美女久久| 久久偷看各类女兵18女厕嘘嘘| 国产精品视频中文字幕91| 日韩在线免费高清视频| 亚洲精品久久久久久久久久久久久| 亚洲性日韩精品一区二区| 日韩欧美大尺度| 九九久久精品一区| 久久国产色av| 日产日韩在线亚洲欧美| 国产精品午夜视频| 精品视频在线播放| 国产精品美女免费看| 国产999精品| 91黑丝高跟在线| 欧美天堂在线观看| 国产欧美一区二区三区视频| yellow中文字幕久久| 日韩欧美在线字幕| 久久久久久久国产| 欧美www视频在线观看| 久久手机精品视频| 日韩av在线网站| 亚洲国产精品美女| 日日骚av一区| 日韩一级裸体免费视频| 国产精品99久久久久久人| 国产精品成人一区| 日韩av高清不卡| 久久精品国产亚洲精品2020| 亚洲精品国产美女| 97视频网站入口| 亚洲一区二区三区乱码aⅴ蜜桃女| 911国产网站尤物在线观看| 亚洲精品乱码久久久久久金桔影视| 欧美激情久久久久| 国产精品88a∨| 亚洲一区二区三区视频| 久久久精品免费| 国产成人精品电影| 97视频在线观看网址| 色妞欧美日韩在线| 性色av一区二区咪爱| 精品久久久视频| 秋霞av国产精品一区| 日韩专区在线播放| 国产一区二区丝袜高跟鞋图片| 欧美三级xxx| 51精品在线观看| 亚洲xxxx18| 国产成人亚洲综合91精品| 日韩激情片免费| 国产精品日日做人人爱| 中文字幕亚洲欧美日韩在线不卡| 国产精品视频久久| 精品久久中文字幕| 欧美国产日本在线| 欧美在线不卡区| 91黄色8090| 日韩av最新在线| 精品国产区一区二区三区在线观看| 久久夜精品va视频免费观看| 欧美电影电视剧在线观看| 亚洲国产福利在线| 57pao成人永久免费视频| 亚洲毛茸茸少妇高潮呻吟| 国产精品国产福利国产秒拍| 亚洲一区二区免费在线| 亚洲欧美在线免费| 91久久国产精品| 亚洲欧美激情精品一区二区| 日韩免费在线免费观看| 尤物yw午夜国产精品视频明星| 97视频在线免费观看| 亚洲精品国产精品国自产观看浪潮| 国产精品视频26uuu| 亚洲精品电影在线| 亚洲第一天堂无码专区| 欧美视频专区一二在线观看| 亚洲美女视频网站| 国产不卡av在线| 亚洲一区二区三区sesese| 国产欧美精品在线| 国产美女搞久久| 日韩欧美第一页| 国产免费观看久久黄| 久久av在线播放| 欧美日韩亚洲一区二区三区| 国产欧美精品va在线观看| 亚洲黄色有码视频| 久久久久免费精品国产|