微信登錄獲取掃碼結果的原理

之前面試,有個面試官問我微信掃碼登錄的原理,當時我沒具體的看過,就說了一下自己的猜想。

用戶訪問網頁版登錄界面,登錄頁面動態生成一個登錄鏈接,應該帶有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長鏈接請求,超時重新請求的意思麼?

發佈了48 篇原創文章 · 獲贊 104 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章