• <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 .

            騰訊的網(wǎng)站如何檢測到你的 QQ 已經(jīng)登錄?

            轉(zhuǎn)載自:http://www.lovelucy.info/tencent-sso.html

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

            Qzone_AutoLogin

            QQMail_AutoLogin

            網(wǎng)上有很多猜測,比如——

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

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

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

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

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

            Tencent_SSO_plugin

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

            有點不懷好意的想法開始萌生,我自己的網(wǎng)站能否借用這個插件來檢測用戶的 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 中就對域名進行了限制,網(wǎng)頁是無法篡改的。于是修改本地host文件,加一條:

            127.0.0.1 xui.ptlogin2.qq.com

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

            TencentSsoTesting

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

            PS. Chrome 瀏覽器自帶的開發(fā)者工具有一個功能可以格式化被壓縮的 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)  編輯 收藏 引用


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            区亚洲欧美一级久久精品亚洲精品成人网久久久久 | 久久综合久久自在自线精品自| 久久精品国产91久久综合麻豆自制 | 久久免费精品视频| 婷婷久久久亚洲欧洲日产国码AV| 久久中文字幕视频、最近更新| 久久青青草原精品影院| 久久综合久久自在自线精品自 | 欧洲精品久久久av无码电影| 狠狠色丁香婷婷久久综合五月| 99久久精品国产一区二区三区| 狠狠久久亚洲欧美专区| 国产精品99久久久久久人| 国产成人久久激情91| 久久久久久毛片免费播放| 久久香蕉国产线看观看精品yw| 久久精品国产亚洲av麻豆蜜芽 | 人妻久久久一区二区三区| 久久久精品国产免大香伊| 久久亚洲精品无码aⅴ大香| 欧美日韩久久中文字幕| 99久久国产亚洲综合精品| 热久久视久久精品18| 中文无码久久精品| 欧美熟妇另类久久久久久不卡| 久久夜色精品国产噜噜亚洲AV| 99久久er这里只有精品18| 久久99精品久久久久久| 办公室久久精品| 午夜精品久久久久9999高清| 久久综合亚洲色一区二区三区| 亚洲综合伊人久久大杳蕉| 国产精品一久久香蕉国产线看观看 | 2021久久精品免费观看| 精品久久亚洲中文无码| 国内精品久久久久伊人av| 91精品婷婷国产综合久久| 伊人久久大香线蕉综合5g| 久久精品国产亚洲AV嫖农村妇女| 99久久亚洲综合精品成人| 国产精品久久久久蜜芽|