在Python中用Request庫模擬登陸(四):嗶哩嗶哩(有加密,有驗證碼)

 !已失效!

抓包分析

獲取驗證碼html

獲取加密公鑰web

其中hash是變化的,公鑰key不變ajax

登陸json

其中用戶名沒有被加密,密碼被加密。瀏覽器

由於在獲取公鑰的時候同時返回了一個hash值,推測此hash值與密碼加密有關。session

經過谷歌瀏覽器控制檯分析js代碼

 右鍵登陸按鈕,檢查,查看 Event Listeners ,點擊a.btn.btn-login右邊的login.4f030c3....js:6查看js代碼。dom

點擊左下角的{}展開代碼async

由於獲取公鑰和hash的連接中有action=getkey,嘗試在源代碼中搜索getkey,因而找到這樣一個函數:函數

 1 encryptPassword: function (e, t) {
 2     var n = this,
 3     r = !1;
 4     return $.ajax({
 5         url: "https://passport.bilibili.com/login?act=getkey&r=" + Math.random(),
 6         async: !1
 7     }).done(function (t) {
 8         t && t.error && (n.publicTip = "登陸失敗,服務端出現異常", e = null);
 9         var i = new JSEncrypt;
10         i.setPublicKey(t.key);
11         var a = i.encrypt(t.hash + e);
12         e = a,
13         r = !0
14     }),
15     r ? e : ""
16 }

 觀察第十、11行,可知hash和變量e相加後被RSA加密,如今須要肯定e是什麼。在第11行代碼所在的位置設置一個斷點,輸入用戶名密碼驗證碼以後點擊登陸,在這裏密碼框輸入的是‘mypassword’post

點擊e就會顯示出e的值,看來e就是密碼明文。

因而,能夠猜想,加密的過程是:密碼字符串前面串接hash值,而後進行RSA加密。下面經過測試檢查猜想是否正確。

模擬登陸

每一次請求的headers都徹底複製抓包的內容。

1.獲取驗證碼

1 def get_code():
2     url='https://passport.bilibili.com/captcha?r=0.1265352187487443'
3     headers={複製抓包到的headers}
4     session.headers.clear()
5     session.headers.update(headers)
6     r=session.get(url)
7     file=open('code.jpg','wb')
8     file.write(r.content)
9     file.close()

2.getkey

1 def get_key():
2     url='https://passport.bilibili.com/login?act=getkey&r=0.4365052982637341'
3     headers={複製抓包到的headers}
4     session.headers.clear()
5     session.headers.update(headers)
6     r=session.get(url)
7     jsondata=json.loads(r.text)
8     #hash變化,key不變
9     return (jsondata['hash'],jsondata['key'])

3.加密,具體能夠參考博客園的模擬登陸的附錄部分

1 def encrypt(Hash,key,password):
2     from Crypto.PublicKey import RSA
3     from Crypto.Cipher import PKCS1_v1_5
4     from base64 import b64encode
5     encryptor=PKCS1_v1_5.new(RSA.importKey(bytes(key,'utf-8')))
6     return str(b64encode(encryptor.encrypt(bytes(Hash+password,'utf-8'))),'utf-8')

4.登陸

 1 def login(code,username,password):
 2     #注意,在登陸頁面中驗證碼會自動轉成大寫
 3     url='https://passport.bilibili.com/web/login'
 4     headers={複製抓包到的headers}
 5     data={'cType':'2',
 6           'vcType':'1',
 7           'captcha':code,
 8           'user':username,
 9           'pwd':password,
10           'keep':'true',
11           'gourl':'http://www.bilibili.com/'}
12     session.headers.clear()
13     session.headers.update(headers)
14     r=session.post(url,data=data)
15     return r.text

若是登陸成功,將返回 "code":0

5.測試

testurl='https://www.bilibili.com/account/dynamic'

在未登陸時,testurl的標題爲「bilibili - 提示」,登陸時標題爲「嗶哩嗶哩 (゜-゜)つロ 乾杯~-bilibili」

session.headers.clear()
r=session.get(testurl)
p=r.text.find('<title>')+len('<title>')
print(r.text[p:r.text.find('<',p)])
相關文章
相關標籤/搜索