获取验证码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)])