这几天工作不忙,研究了新浪微博的登录.
肯定是先抓包,得到登录的url为http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18)
然后输入用户名,密码,在点击登录之前,我们可以在chrome浏览器上给Mouse的click设置一个断点,这样,方便debug我们点击登录按钮的时候,网站会对我们输入的内容作了哪些操作.
通过反复的的debug,我观察到点击登录之后,网站会在成功登录之前做三件关键的事情:
1. 给用户名加密:
加密js代码如图:
可以看到,这里是给用户名做了base64加密.所以,我们可以利用python也把用户名做base64加密
username = "username"
su = base64.encodestring(username)`
2. 发送预登录请求,获得一些登录参数
预登录得到的参数是用来登录和对密码加密的
python代码如下
ssion = requests.session()
prelogin_url = 'http://login.sina.com.cn/sso/prelogin.php?entry=sso&callback=sinaSSOController.preloginCallBack&su=%s&rsakt=mod&client=ssologin.js(v1.4.4)' % su
response = ssion.get(prelogin_url)
content = response.text
结果:
sinaSSOController.preloginCallBack({"retcode":0,"servertime":1553147211,"pcid":"tc-4e88ab7972cc38b9dbebc76e6da23131b496","nonce":"P1ROHE","pubkey":"EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443","rsakv":"1330428213","is_openlock":0,"exectime":7})
3. 对密码做rsa加密
加密js代码如图:
如果懂一些js的话和加密知识的话,可知这是对密码做了rsa加密,
首先创建一个“rsa”公钥,公钥的两个参数都是固定值,第一个参数是预登录的pubkey,第二个参数是指定的“10001”(这两个值需要先从16进制转换成10进制,把“10001”转成十进制为“65537”)。最后再加入“servertime”和“nonce”进行进一步加密。
我们可以在把源代码复制出来,在复制出的js代码里添加一个获取加密代码的js函数:
function get_cp(rsaPubkey, servertime, nonce, password){
var RSAKey = new sinaSSOEncoder.RSAKey()
var RSAKey = new sinaSSOEncoder.RSAKey();
RSAKey.setPublic(rsaPubkey, "10001");
password = RSAKey.encrypt([servertime, nonce].join("\t") + "\n" + password)
return password
}
然后使用pyexecjs来执行获得结果.在python代码里直接使用pyexecjs会报错.需要修改一些.
在js代码里定义好navigator为一个字典,添加需要的属性;alert删掉;还有转移符处理一下.
由于js代码过长,不再粘贴了,后期上传到github上.
可以看一下执行的结果:
上面的username也可以直接用上面的方法得出.
也可以直接使用python来做rsa加密,加密参数使用js里的参数就行:
rsa加密代码
def get_sp():
rsaPublickey = int(pubkey, 16)
key = rsa.PublicKey(rsaPublickey, int("10001", 16)) # 创建公钥
message = servertime + '\t' + nonce + '\n' + password # 拼接明文js加密文件中得到
passwd = rsa.encrypt(message, key) # 加密
passwd = binascii.b2a_hex(passwd) # 将加密信息转换为16进制。
return sp
这样的话也可以得到加密后的password.
4. 登录
通过以上几步把登录需要的参数都拿到了.接下来发送post请求登录就可以了.
postdata = {
"entry": "sso",
"gateway": "1",
"from": "null",
"savestate": "30",
"useticket": "0",
"pagerefer": "http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18)",
"vsnf": "1",
"su": su,
"service": "sso",
"servertime": servertime,
"nonce": nonce,
"pwencode": "rsa2",
"rsakv": rsakv,
"sp": sp,
"sr": "1366*768",
"encoding": "UTF-8",
"cdult": "3",
"domain": "sina.com.cn",
"prelt": "16",
"returntype": "TEXT",
}
header = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36",
}
response = ssion.post(login_url, data=postdata, headers=header)
result = json.loads(response.text)
print result['nick']
注意,我这里使用的是requests.session().原因我在前面的博客也说了,他可以保持会话,不需要手动添加cookie了.
运行结果如图: