獲取驗證碼html
獲取加密公鑰web
其中hash是變化的,公鑰key不變ajax
登陸json
其中用戶名沒有被加密,密碼被加密。瀏覽器
由於在獲取公鑰的時候同時返回了一個hash值,推測此hash值與密碼加密有關。session
右鍵登陸按鈕,檢查,查看 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)])