微信扫描二维码登录网页是什么原理,前后两个事件是如何联系的-
在电脑上使用微信时,你可能已经发现微信不提供传统的账号密码登陆,取而代之的是通过扫描二维码进行登陆。今天就要研究下次登陆方式微信时如何实现的?
1、每次用户打开PC端登陆请求,系统返回一个唯一的uid,并将uid的信息绘制成二维码返回给用户。这里的uid一定是唯一的,否则就会造成你登陆了其他用户的账号或者其他用户登陆你的账号。
2、当用户使用登陆后的微信扫描该二维码的时候,会将这个uid和手机上的微信账号及密码产生的token进行绑定,并上传到服务器。
3、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(/(.*)/);
if(code){
eval(code[1]);
}else{
$("#container").show();
$("#login_container").hide();
}
});
_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();
_logInPage("First Request Success");
_reportNow("/cgi-bin/mmwebwx-bin/login, First Request Success, uuid: " + _asUUID);
// setTimeout(function(){
_logInPage("Second Request Start");
_reportNow("/cgi-bin/mmwebwx-bin/login, Second Request Start, uuid: " + _asUUID);
_sSecondRequestTime = new Date().getTime();
_nAjaxTimeout = 5 * 1000;
_self(_asUUID);
// }, 500);
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);
});
}
}
});
}
网页客户端每500毫秒就向服务器发起ssl请求,请求当前二维码的登陆信息,如果返回结果201,则说明已经获取扫描二维码终端相同的账号登陆授权,当返回其他结果时,将在500毫秒之后重新发起请求。
类似微信登陆场景应用场景还是很多,比如通过二维码进行设备间的授权。比如使用手机遥控 装有android系统的电视盒等。
浏览器获得一个临时 id,通过长连接等待客户端扫描带有此 id 的二维码后,从长连接中获得客户端上报给 server 的帐号信息进行展示,并在客户端点击确认后,获得服务器授信的令牌,进行随后的信息交互过程。 在超时、网络断开、其他设备上登录后,此前获得的令牌或丢失、或失效,有效完成了安全防护。
电脑请求网页后,微信服务器生成一个唯一的ID(这里是UUID)给客户端网页,客户端定时发起向微信服务器的连接(这里类似于轮询),微信服务器保持这个连接(这里类似于长连接),保持一段时间(大概27秒)返回一个逗还没人扫码地的标识,于是客户端再开连接手机微信扫码并解码,解码出来是一个URL也好,是一段文本也好,总之这段东西匹配了手机微信登陆网页版的要求,于是手机微信带着解码出来的信息去请求微信服务器。这里就已经达到了特定微信账号和某个特定网页相关联的目的电脑这里微信服务器马上在长连接中返回逗有人扫码了地的表示并结束连接,网页提示扫描成功,然后打开长连接等待确认登陆的标识;手机这里么则根据二维码的信息打开对应网页确认登陆
后面其实和前面一样了,手机微信确认登陆的其实就是请求服务器说这个可以登录了,然后服务器给网页的长连接中返回可以登录的标识并结束长连接,然后跳转到消息网页