Created by Wang, Jerry, last modified on Dec 10, 2014
在电脑上使用微信时,你可能已经发现微信不提供传统的账号密码登陆,取而代之的是通过扫描二维码进行登陆。今天就要研究下次登陆方式微信时如何实现的?
每次用户打开PC端登陆请求,系统返回一个唯一的uid,并将uid的信息绘制成二维码返回给用户。这里的uid一定是唯一的,否则就会造成你登陆了其他用户的账号或者其他用户登陆你的账号。
当用户使用登陆后的微信扫描该二维码的时候,会将这个uid和手机上的微信账号及密码产生的token进行绑定,并上传到服务器。
WEB通过JS不断的向后端发起请求,查询有没有关于uid的登陆记录(uid和token是否存在于服务器上)。实现代码可以从微信页面获取:
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);
$.get(_aoWin.redirect_uri + "&fun=new", function(msg) {
_logInPage("new func reponse, reponseMsg: " + msg);
_reportNow("new func reponse, reponseMsg: " + msg);
var code = msg.match(/(.*)<\/script>/);</div><div> if(code){</div><div> eval(code[1]);</div><div> }else{</div><div> $("#container").show();</div><div> $("#login_container").hide();</div><div> }</div><div> });</div><div> _reportNow("/cgi-bin/mmwebwx-bin/login, Second Request Success, uuid: " + _asUUID + ", time: " + _sSecondRequestTime + "ms");</div><div> break;</div><div> case 201:</div><div> clearTimeout(_oResetTimeout);</div><div> show_tip = 0;</div><div> $('.errorMsg').hide();</div><div> $('.normlDesc').hide();</div><div> $('.successMsg').show();</div><div> _logInPage("First Request Success");</div><div> _reportNow("/cgi-bin/mmwebwx-bin/login, First Request Success, uuid: " + _asUUID);</div><div>// setTimeout(function(){</div><div> _logInPage("Second Request Start");</div><div> _reportNow("/cgi-bin/mmwebwx-bin/login, Second Request Start, uuid: " + _asUUID);</div><div> _sSecondRequestTime = new Date().getTime();</div><div> _nAjaxTimeout = 5 * 1000;</div><div> _self(_asUUID);</div><div>// }, 500);</div><div> break;</div><div> case 408:</div><div> setTimeout(function(){</div><div> _self(_asUUID);</div><div> }, 500);</div><div> break;</div><div> case 400:</div><div> case 500:</div><div> _reset();</div><div> _afterLoadWebMMDo(function(){</div><div> _aoWin.Log.d("500, Login Poll Svr Exception");</div><div> });</div><div> break;</div><div> }</div><div> },</div><div> error: function(jqXHR, textStatus, errorThrown) {</div><div> if (textStatus == 'timeout') {</div><div> setTimeout(function(){</div><div> _self(_asUUID);</div><div> }, 500);</div><div> } else {</div><div> setTimeout(function(){</div><div> _self(_asUUID);</div><div> }, 5000);</div><div> _logInPage("_poll Request Error:" + textStatus);</div><div> _afterLoadWebMMDo(function(){</div><div> _aoWin.Log.e("Login Poll Error:" + textStatus);</div><div> });</div><div> }</div><div> }</div><div> });</div><div> }</div><div><span data-card-type="inline" data-ready-card="image" data-card-value="data:%7B%22src%22%3A%22https%3A%2F%2Fucc.alicdn.com%2Fpic%2Fdeveloper-ecology%2F4ffd1deb58d04f61940da851db487d9e.png%22%2C%22originWidth%22%3A776%2C%22originHeight%22%3A741%2C%22name%22%3A%22image.png%22%2C%22size%22%3A68578%2C%22display%22%3A%22inline%22%2C%22align%22%3A%22left%22%2C%22linkTarget%22%3A%22_blank%22%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22search%22%3A%22%22%2C%22margin%22%3A%7B%22top%22%3Atrue%2C%22bottom%22%3Atrue%7D%2C%22width%22%3A776%2C%22height%22%3A741%7D"></span></div><div><span data-card-type="inline" data-ready-card="image" data-card-value="data:%7B%22src%22%3A%22https%3A%2F%2Fucc.alicdn.com%2Fpic%2Fdeveloper-ecology%2Fc89f090e38e6487c85b25f7fdab0dd79.png%22%2C%22originWidth%22%3A764%2C%22originHeight%22%3A764%2C%22name%22%3A%22image.png%22%2C%22size%22%3A55638%2C%22display%22%3A%22inline%22%2C%22align%22%3A%22left%22%2C%22linkTarget%22%3A%22_blank%22%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22search%22%3A%22%22%2C%22margin%22%3A%7B%22top%22%3Atrue%2C%22bottom%22%3Atrue%7D%2C%22width%22%3A764%2C%22height%22%3A764%7D"></span></div><div>网页客户端每500毫秒就向服务器发起ssl请求,请求当前二维码的登陆信息,如果返回结果201,则说明已经获取扫描二维码终端相同的账号登陆授权,当返回其他结果时,将在500毫秒之后重新发起请求。</div><div>类似微信登陆场景应用场景还是很多,比如通过二维码进行设备间的授权。比如使用手机遥控 装有android系统的电视盒等。</div><div><span data-card-type="inline" data-ready-card="image" data-card-value="data:%7B%22src%22%3A%22https%3A%2F%2Fucc.alicdn.com%2Fpic%2Fdeveloper-ecology%2F10f3f92cc1e64990b6722764d6991403.png%22%2C%22originWidth%22%3A788%2C%22originHeight%22%3A501%2C%22name%22%3A%22image.png%22%2C%22size%22%3A201218%2C%22display%22%3A%22inline%22%2C%22align%22%3A%22left%22%2C%22linkTarget%22%3A%22_blank%22%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22search%22%3A%22%22%2C%22margin%22%3A%7B%22top%22%3Atrue%2C%22bottom%22%3Atrue%7D%2C%22width%22%3A788%2C%22height%22%3A501%7D"></span></div><div><br /></div>