之前面試,有個面試官問我微信掃碼登錄的原理,當時我沒具體的看過,就說了一下自己的猜想。
用戶訪問網頁版登錄界面,登錄頁面動態生成一個登錄鏈接,應該帶有token之類的,這時候網頁開始不停的給服務器發送請求,輪訓用戶是否已經掃碼成功。用戶用微信客戶端掃碼,掃碼之後微信客戶端向服務器發送一個請求,告訴服務器用戶掃碼成功,此時可以update一個標誌,在網頁版微信下次輪詢登錄狀態時,獲取到掃碼成功的命令。
當時我是這麼回答的,然後面試官問我,網頁端怎麼去輪詢呢,我就說了用ajax去請求,設定一個超時時間,如果在指定時間內未獲取掃碼結果,超時返回。然後面試官說不對,說我肯定用過。當時我就開始想,還有更牛逼的技術麼。回來就看微信的網頁版js代碼。摘錄在下面了。
從瀏覽器數據包上看,微信網頁版會每隔27秒就會發送一個登錄掃碼的請求。具體的js代碼在https://res.wx.qq.com/zh_CN/htmledition/v2/js/webwxApp2e4e03.js
這個js文件中,下面摘除部分主要代碼。
function a(i) {
switch (i.code) {
case 200:
t.newLoginPage(i.redirect_uri).then(function(t) {
var r = t.match(/<ret>(.*)<\/ret>/),
a = t.match(/<script>(.*)<\/script>/),
i = t.match(/<skey>(.*)<\/skey>/),
c = t.match(/<wxsid>(.*)<\/wxsid>/),
s = t.match(/<wxuin>(.*)<\/wxuin>/),
l = t.match(/<pass_ticket>(.*)<\/pass_ticket>/),
u = t.match(/<redirecturl>(.*)<\/redirecturl>/);
return u ? void(window.location.href = u[1]) : (e.$emit("newLoginPage", {
Ret: r && r[1],
SKey: i && i[1],
Sid: c && c[1],
Uin: s && s[1],
Passticket: l && l[1],
Code: a
}), void(o.getCookie("webwx_data_ticket") || n.report(n.ReportType.cookieError, {
text: "webwx_data_ticket 票據丟失",
cookie: document.cookie
})))
});
break;
case 201:
e.isScan = !0,
n.report(n.ReportType.timing, {
timing: {
scan: Date.now()
}
}),
t.checkLogin(r).then(a);
break;
case 408:
t.checkLogin(r).then(a);
break;
case 400:
case 500:
case 0:
document.location.reload()
}
e.code = i.code,
e.userAvatar = i.userAvatar,
o.log("get code", i.code)
}
case 塊,通過判斷不同的返回碼,做出不同的操作,200 代表掃碼成功,408代表未掃碼,繼續檢查。下面是checkLogin(r)
的代碼
checkLogin: function(e, o) {
var n = t.defer(),
o = o || 0;
return window.code = 0,
$.ajax({
url: r.API_login + "?loginicon=true&uuid=" + e + "&tip=" + o + "&r=" + ~new Date,
dataType: "script",
timeout: 35e3
}).done(function() {
if (new RegExp("/" + location.host + "/"), window.redirect_uri && window.redirect_uri.indexOf("/" + location.host + "/") < 0) return void(location.href = window.redirect_uri);
var e = {
code: window.code,
redirect_uri: window.redirect_uri,
userAvatar: window.userAvatar
};
n.resolve(e)
}),
n.promise
}
我對前端不是很瞭解,難道這不是ajax長鏈接請求,超時重新請求的意思麼?