有園友私信我探討關於博客園模擬登陸的事,年前也玩了一段時間的 node(詳情能夠參考個人 node 項目集 https://github.com/hanzichi/funny-node 厚着臉皮求 star),作以前想的可能只是一次簡單的 post,嘗試下來完成後仍是有了很多收穫。爲了能讓後人有個參考,遂成此文。php
閒話少說,既然是模擬登陸,咱們來看看登陸過程都發生了什麼。html
打開登陸頁面(http://passport.cnblogs.com/user/signin?ReturnUrl=http://passport.cnblogs.com/),填入用戶名和密碼,點擊登陸後,咱們很容易地抓到了登陸包。node
先看返回頭:git
後續的實踐中,我用回帖操做來證實已經完成登陸。抓取回帖的包,發現回帖操做須要攜帶一個 key 爲 .CNBlogsCookie 的 cookie 識別身份。又發現,只要一次登陸後將瀏覽器中的該 cookie 取出,就能模擬該用戶了。我將客戶端的 key 爲 .CNBlogsCookie 的 cookie 取出,寫下以下代碼:github
superagent .post('http://www.cnblogs.com/mvc/PostComment/Add.aspx') .set("Cookie", ".CNBlogsCookie=yourCookieValue") .send({"blogApp": "xxx"}) .send({"body": "test"}) .send({"postId": xxx}) .end(function (err, sres) { // callback });
竟然能回帖,徹底不用管其餘操做了。不明緣由,可是細思極恐,若是你被人盜取了該 cookie,後果你懂的。ajax
要手動從瀏覽器中複製獲取該 cookie 顯得有點 low,如何能自動獲取該 cookie 值?算法
再看請求頭:瀏覽器
實踐發現,有四個值是必須模擬的(已標出),並且全都照抄便可。安全
最後看 post 的數據:cookie
這是什麼玩意?原來是加密後的用戶名以及密碼數據。接下去簡單瞭解下加密方式(儘管模擬登陸並不強依賴於此)。
博客園的加密方式爲 RSA,依賴 jsencrypt 這個庫。
這裏不詳述 RSA 加密方式,詳情能夠參考阮一峯老師的文章:
jsencrypt 加密是可逆的加密方式,客戶端用公鑰加密,服務端用私鑰解密,每次加密生成的字符串都不同,可是解密後都同樣。用明文發送帳戶名和密碼,若是該包被截獲,那麼你的密碼也將大白於天下,存在着極大的安全隱患,可是客戶端用了 jsencrypt 加密,若是被截獲,截獲的也僅僅只是加密後的字符串,沒有私鑰解密的話,也無濟於事。咱們 post 包中的 input1 和 input2 的數據正是在客戶端加密後的用戶名以及密碼。
打開 http://passport.cnblogs.com/user/signin?ReturnUrl=http://passport.cnblogs.com,ctrl+u 查看網頁源代碼,能夠清楚看到 jsencrypt 加密的公鑰,帳戶名密碼的加密過程,以及用 ajax 方式登陸所須要的數據等。
參考 博客園加密登陸--jsencrypt 我寫了個簡單的基於 jsencrypt 的加密解密 demo https://github.com/hanzichi/funny-node/tree/master/cnblogs-auto-login/jsencrypt-demo。由於解密過程有用到 PHP 中的 openssl,因此記得在 php.ini 文件中打開 openssl,具體操做爲找到 extension=php_openssl.dll
這一行,把註釋打開(將前面的封號去掉)。
另外,根據已經披露的文獻,目前被破解的最長 RSA 密鑰是 768 個二進制位。也就是說,長度超過 768 位的密鑰,還沒法破解(至少沒人公開宣佈)。所以能夠認爲,1024 位的 RSA 密鑰基本安全,2048 位的密鑰極其安全。Online RSA Key Generator 能夠參考 http://travistidwell.com/jsencrypt/demo/index.html,我這也備份了一份 https://github.com/hanzichi/funny-node/tree/master/cnblogs-auto-login/key-generator。
進入最後編碼階段。
首先咱們須要獲取加密後的帳戶名以及密碼,能夠抓個包複製下參數,雖然每次加密後的字符串都不同,可是解密後的結果是同樣的,因此若是後期不主動修改用戶名和密碼,這樣作徹底沒有問題。可是我以爲這樣作不優雅,能不能經過用戶名和密碼,獲取加密後的結果?嘗試着找了下 node 下的 RSA 模塊,無奈可能使用方式不大同樣,未果。因而換了個方式,客戶端進行加密,將加密後的數據存儲到服務端,供 node 調用。
而後就是模擬登陸了,VerificationToken 參數能夠爬取頁面取,也能夠直接拿個值賦值。登陸成功後保存 cookie 以便下次操做時調用。
詳細代碼和操做步驟已同步在 Github,歡迎交流探討。