• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            騰訊的網站如何檢測到你的 QQ 已經登錄?

            轉載自:http://www.lovelucy.info/tencent-sso.html

            在 QQ 已經登錄的情況下,手動輸入網址打開 QQ 郵箱 或者 QQ 空間 等騰訊網站,可以看到網頁已經檢測到本地 QQ 客戶端已經登錄,于是用戶可以很方便地一鍵登錄網站而不必再輸入用戶名密碼。這實際上是典型的異構系統單點登錄 SSO(single-sign-on)技術。網頁怎么會知道我登錄的 QQ 號碼?騰訊是如何實現的呢?

            Qzone_AutoLogin

            QQMail_AutoLogin

            網上有很多猜測,比如——

            • QQ 登錄時在本地某地方存登錄 ID 信息(Cookie 或文件),用 js 讀,然后去服務器認證。但是現在的瀏覽器一般有沙箱功能,js 無法讀到登錄 ID;而且在清空 Cookie 后依然起作用。
            • 以 IP、CPU ID、硬盤 ID 等硬件設備 hash 做唯一標識,QQ 登錄時在服務器記錄此信息,js 驗證。感覺這樣依賴環境過多,QQ 不太可能采用此方法。
            • QQ 啟動某端口監聽,js 連接此端口。但是用 netstat 查看后,QQ 并沒有監聽端口。

            有這么一個神奇的鏈接,http://xui.ptlogin2.qq.com/cgi-bin/qlogin 你一點開,它就檢測到你登錄了 QQ。通過查看頁面源代碼,我們可以發現一個關于 ptlogin 的 js 文件,這段代碼中,描述了使用 ActivexObject 瀏覽器插件的過程,于是一切了然。

            可是 ActiveX 是 IE 的插件呀,我們使用 Chrome 或者 FireFox 也是可以直接登錄的,這是怎么回事呢?

            原來,QQ 使用了歷史很悠久的 NPAPI(Netscape Plugin Application Programming Interface)接口。NPAPI 幾乎支持所有主流瀏覽器,包括 FireFox、Chrome、Opera(IE 從 5.5 后停止支持 NPAPI,轉而使用 ActiveX)。

            打開 chrome://plugins/ 我們可以發現自動登錄的有關插件,而在路徑 C:\Program Files (x86)\Common Files\Tencent\TXSSO 下就可以找到關于 SSO 的相關動態鏈接庫。

            Tencent_SSO_plugin

            np 插件一般命名都會加np前綴 如 QQ 的這個 npSSOAxCtrlForPTLogin.dll,只要按照標準的寫法,放在瀏覽器會加載的地方,用的時候寫個標簽就可以在 js 里面調用了。于是跨瀏覽器(無視 IE)的插件開發變得相當可行。運行在 NPAPI 插件中的代碼擁有當前用戶的所有權限,不在沙箱中運行,所以它的擴展程序在被 Chrome 網上應用店接受前要求人工審核。

            有點不懷好意的想法開始萌生,我自己的網站能否借用這個插件來檢測用戶的 QQ 登錄呢?寫個頁面測試一下。

            <!DOCTYPE html>
                        <html>
                        <head>
                        <meta charset="utf-8">
                        <title>Tencent SSO Testing</title>
                        </head>
                        <body>
                        <script>
                        var g_vOptData;
                        var mylocation= "xui.ptlogin2.qq.com/cgi-bin1/qlogintest.html";
                        var pt = {
                        ishttps: false,
                        low_login: 0,
                        keyindex: 9,
                        init: function()
                        {
                        pt.ishttps = /^https/.test(mylocation);
                        //if (navigator.mimeTypes["application/nptxsso"]) {
                        var B = document.createElement("embed");
                        B.type = "application/nptxsso";
                        B.style.width = "0px";
                        B.style.height = "0px";
                        document.body.appendChild(B);
                        pt.sso = B
                        }
                        };
                        pt.init();
                         
                        try {
                        if (window.ActiveXObject)
                        {
                        q_hummerQtrl = new ActiveXObject("SSOAxCtrlForPTLogin.SSOForPTLogin2");
                        var A = q_hummerQtrl.CreateTXSSOData();
                        q_hummerQtrl.InitSSOFPTCtrl(0, A);
                        g_vOptData = q_hummerQtrl.CreateTXSSOData()
                        }
                        hummer_loaduin();
                        } catch(B) {
                        alert(/create ActiveXObject failed/)
                        }
                         
                        function hummer_loaduin()
                        {
                        if (window.ActiveXObject)
                        {
                        var Y = q_hummerQtrl.DoOperation(1, g_vOptData);
                        if (null == Y) {
                        return
                        }
                        try
                        {
                        var T = Y.GetArray("PTALIST");
                        var c = T.GetSize();
                        var X = "";
                        for (var d = 0; d < c; d++)
                           {
                            var E = T.GetData(d);
                            var a = E.GetDWord("dwSSO_Account_dwAccountUin");
                            var J = "";
                            var O = E.GetByte("cSSO_Account_cAccountType");
                            var b = a;
                            if (O == 1)
                            {
                             try
                             {
                              J = E.GetArray("SSO_Account_AccountValueList");
                              b = J.GetStr(0)
                             } catch(Z) {}
                            }
                            var Q = 0;
                            try {
                            Q = E.GetWord("wSSO_Account_wFaceIndex")
                            } catch(Z) {
                            Q = 0
                            }
                            var S = "";
                            try {
                            S = E.GetStr("strSSO_Account_strNickName")
                            } catch(Z) {
                            S = ""
                            }
                            var F = E.GetBuf("bufGTKey_PTLOGIN");
                            var G = E.GetBuf("bufST_PTLOGIN");
                            var N = "";
                            var A = G.GetSize();
                            for (var W = 0; W < A; W++) {
                            var B = G.GetAt(W).toString("16");
                            if (B.length == 1) {
                            B = "0" + B
                            }
                            N += B
                            }
                            var M = {
                             uin: a,
                             name: b,
                             type: O,
                             face: Q,
                             nick: S,
                             key: N
                            };
                            var str = "QQinfo\r\n"+
                                "uin:" + M['uin']+"\r\n"+
                                "name:"+M['name']+"\r\n"+
                                "type:"+M['type']+"\r\n"+
                                "face:"+M['face']+"\r\n"+
                                "nick:"+M['nick']+"\r\n"+
                                "key:"+M['key']+"\r\n";
                            alert(str);
                            q_aUinList[d] = M
                           }
                          } catch(Z) {}
                          } else
                          {
                          try {
                           var M = pt.sso;
                           var L = M.InitPVA();
                           if (L != false)
                           {
                            var I = M.GetPVACount();
                            for (var W = 0; W < I; W++)
                            {
                             var C = M.GetUin(W);
                             var D = M.GetAccountName(W);
                             var K = M.GetFaceIndex(W);
                             var U = M.GetNickname(W);
                             var P = M.GetGender(W);
                             var V = M.GetUinFlag(W);
                             var f = M.GetGTKey(W);
                             var R = M.GetST(W);
                            }
                            var str = "QQinfo\r\n"+
                                "uin:" + C +"\r\n"+
                                "name:"+D+"\r\n"+
                                "face:"+K +"\r\n"+
                                "nick:"+U+"\r\n"+
                                "key:"+f+"\r\n";
                            alert(str);
                           }
                          } catch(Z) {}
                          }
                         
                        }
                        </script>
                        </body>
                        </html>

            本地打開此頁面,create ActiveXObject 失敗。騰訊必然在 dll 中就對域名進行了限制,網頁是無法篡改的。于是修改本地host文件,加一條:

            127.0.0.1 xui.ptlogin2.qq.com

            再用 xui.ptlogin2.qq.com 這個域名去訪問本地的這個 html,果然,可以正常拿到 QQ 相關信息。

            TencentSsoTesting

            好吧,這個截圖被我打碼打得沒啥意義了

            PS. Chrome 瀏覽器自帶的開發者工具有一個功能可以格式化被壓縮的 js 代碼,十分好用。廢話不多說,有圖說明一切——

            pretty_print_js_google_chrome

            參考鏈接:
            http://1.lanz.sinaapp.com/?p=152
            http://taurus-ly.com/articles/2012/02/153.html

            posted on 2014-02-24 14:15 楊粼波 閱讀(1052) 評論(0)  編輯 收藏 引用

            日韩亚洲欧美久久久www综合网 | 日韩十八禁一区二区久久| 久久久久久a亚洲欧洲aⅴ| 久久精品嫩草影院| 国产精品伊人久久伊人电影| 99久久99久久精品国产| 久久久久无码专区亚洲av| 久久亚洲色一区二区三区| 99久久国产综合精品女同图片| 漂亮人妻被黑人久久精品| 狠狠色丁香久久综合婷婷| 香港aa三级久久三级老师2021国产三级精品三级在 | 91精品国产91久久久久久蜜臀| 日日狠狠久久偷偷色综合0| 欧美日韩精品久久久久| 久久亚洲精品成人av无码网站| 美女写真久久影院| 久久精品一本到99热免费| 久久人人爽人人爽人人片av麻烦| 九九久久自然熟的香蕉图片| 精品久久人人爽天天玩人人妻| 伊人热热久久原色播放www| 久久人人爽人人爽人人AV东京热| 国内精品免费久久影院| 国产亚洲欧美成人久久片| 久久精品卫校国产小美女| 无码任你躁久久久久久老妇| 国产一级做a爰片久久毛片| 精品伊人久久大线蕉色首页| 午夜精品久久久久9999高清| 国产精品天天影视久久综合网| 久久久久久久久久久久久久| 国产女人aaa级久久久级| 久久99精品久久久久久动态图| 久久99国产精品成人欧美| 久久99精品综合国产首页| 日日噜噜夜夜狠狠久久丁香五月 | 久久精品视屏| yellow中文字幕久久网| 国产成人精品久久综合| 国产精品久久久久久久|