完整源码参考我的pixiv-to-weibo项目,只实现了核心部分,没做容错处理
登录
预登录
这一步是为了获取加密公钥和nonce,因为以前新浪没用HTTPS,必须手动加密。其中用户名编码su算法为BASE64(URI编码(用户名))
async def _pre_login(self, su):
async with self._session.get('https://login.sina.com.cn/sso/prelogin.php', params={
'entry': 'weibo',
'callback': 'sinaSSOController.preloginCallBack',
'su': su,
'rsakt': 'mod',
'checkpin': '1',
'client': 'ssologin.js(v1.4.18)'
}) as r:
return self.__get_jsonp_response(await r.text())
返回方式是JSONP,有用的是这几个字段:用来加密的公钥pubkey
,防止回放攻击的nonce
和servertime
,之后请求要用的rsakv
,是否需要验证码showpin
,验证码请求要用的pcid
获取验证码
如果预登录返回的数据中showpin
为1则需要验证码。获取验证码的请求如下,返回的是验证码图片数据
async def _input_verif_code(self, pcid):
async with self._session.get('https://login.sina.com.cn/cgi/pin.php', params={
'r': random.randint(0, 100000000),
's': '0',
'p': pcid
}) as r:
img_data = await r.read()
self._show_image(img_data)
return input('输入验证码:')
登录
密码密文sp计算
sp算法为:转十六进制文本(RSA(servertime + '\t' + nonce + '\n' + 密码))
,其中RSA公钥在预登录时返回
@staticmethod
def _get_secret_password(password, servertime, nonce, pubkey):
key = rsa.PublicKey(int(pubkey, 16), 65537)
res = rsa.encrypt(f'{servertime}\t{nonce}\n{password}'.encode(), key)
res = binascii.b2a_hex(res)
return res.decode()
登录请求
![登录请求](https://img-blog.csdnimg.cn/20190424190309439.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hmZ3J5dWpr,size_16,color_FFFFFF,t_70)
登录请求如下,这个请求完成后就可以发微博了。很多微博登录的源码都只做到这一步,但是24小时后session会失效,少了后面的步骤则不能恢复session
async def login(self, username, password):
su = base64.b64encode(quote_plus(username).encode()).decode()
data = await self._pre_login(su)
async with self._session.post('https://login.sina.com.cn/sso/login.php', params={
'client': 'ssologin.js(v1.4.19)',
}, data