微博登录和session恢复过程
微博登录和session恢复过程
- 登录
- 预登录
- 获取验证码
- 登录
- 密码密文sp计算
- 登录请求
- 跨域广播登录
- 解决cookie设置不上的问题
- 跨域广播之后
- 恢复session
完整源码参考我的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公钥在预登录时返回
@staticmethoddef _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()
登录请求
登录请求如下,这个请求完成后就可以发微博了。很多微博登录的源码都只做到这一步,但是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={'entry': 'weibo','gateway': '1','from': '','savestate': '7','qrcode_flag': 'false','useticket': '1','pagerefer': 'https://login.sina.com.cn/crossdomain2.php?action=logout&''r=https%3A%2F%2Fpassport.weibo.com%2Fwbsso%2Flogout%3Fr%3''Dhttps%253A%252F%252Fweibo.com%26returntype%3D1','vsnf': '1','su': su,'service': 'miniblog','servertime': data['servertime'],'nonce': data['nonce'],'pwencode': 'rsa2','rsakv': data['rsakv'],'sp': self._get_secret_password(password, data['servertime'],data['nonce'], data['pubkey']),'sr': '1366*768','encoding': 'UTF-8','prelt': '233','url': 'https://weibo.com/ajaxlogin.php?framelogin=1&callback=''parent.sinaSSOController.feedBackUrlCallBack','returntype': 'META','door': '' if data['showpin'] == 0else await self._input_verif_code(data['pcid'])}) as r:return await self.__handle_login_page(str(r.url), await r.text())
返回内容为一个网页,其中有脚本跳转到下一个地址
<html><head><title>新浪通行证</title><meta http-equiv="refresh" content="0; url='https://login.sina.com.cn/crossdomain2.php?action=login&entry=weibo&......'"/><meta http-equiv="Content-Type" content="text/html; charset=GBK" /></head><body bgcolor="#ffffff" text="#000000" link="#0000cc" vlink="#551a8b" alink="#ff0000"><script type="text/javascript" language="javascript">location.replace("https://login.sina.com.cn/crossdomain2.php?action=login&entry=weibo&......");</script></body></html>
微博登录中跳转的网址是不确定的,有时候是https://login.sina.com.cn/crossdomain2.php
,有时候是https://passport.weibo.com/visitor/visitor
,整个流程不能写死,所以我专门写了一个函数来处理这些跳转
async def __handle_login_page(self, url, res):while True:# 登录页if url.startswith('https://login.sina.com.cn/sso/login.php'):next_url = self.__get_next_url(res)# ...# 登录完毕elif url.startswith('https://weibo.com'):return '/home' in url# 未知的地址else:print('未知的地址:' + url)print(res)return Falseasync with self._session.get(next_url, headers={'Referer': url # 访问visitor?a=restore必须带referer}) as r:url = str(r.url)res = await r.text()
跨域广播登录
这是上一步跳转到的crossdomain2.php
干的事,就是你打开微博偶尔会看到的"Signing in …"的页面。旧版sso登录脚本没有混淆并且有中文注释,有兴趣的自己看吧。arrURL
是要发送请求的URL列表,请求完成后调用location.replace
跳转
广播URL中要关注的是passport.weibo.com
这个域名,会设置一些恢复session用的cookie,Python中有些坑会导致这些cookie设置不上,这个后面再说
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK" />
<title>Sina Passport</title><script charset="utf-8" src="https://i.sso.sina.com.cn/js/ssologin.js"></script>
</head>
<body>
Signing in ...
<script>
try{sinaSSOController.setCrossDomainUrlList({"retcode":0,"arrURL":["......"]});}catch(e){var msg = e.message;var img = new Image();var type = 1;img.src = 'https://login.sina.com.cn/sso/debuglog?msg=' + msg +'&type=' + type;}try{sinaSSOController.crossDomainAction('login',function(){location.replace('https://passport.weibo.com/wbsso/login?......');});}catch(e){var msg = e.message;var img = new Image();var type = 2;img.src = 'https://login.sina.com.cn/sso/debuglog?msg=' + msg +'&type=' + type;}
</script>
</body>
</html>
__handle_login_page
中对这个页面的处理如下
# 跨域登录广播elif url.startswith('https://login.sina.com.cn/crossdomain2.php'):async def cross_domain_callback(url_, i):async with self._session.get(url_, params={'callback': 'sinaSSOController.doCrossDomainCallBack','scriptId': 'ssoscript' + str(i),'client': 'ssologin.js(v1.4.2)'}) as r_:await r_.read()url_list = re.search(r'setCrossDomainUrlList\((.*?)\);', res)[1]url_list = json.loads(url_list)['arrURL']await asyncio.gather(*(cross_domain_callback(url, i) for i, url in enumerate(url_list)))next_url = self.__get_next_url(res)
解决cookie设置不上的问题
这个是因为新浪返回的cookie中expire的星期几用的是全称,而Python标准库中的正则假设它用的是3个字符的简称:\w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT
>>> import http.cookies
>>> cookie = http.cookies.SimpleCookie()
>>> cookie.load('SRF=155......; expires=Sunday, 15-Apr-2029 13:18:56 GMT; path=/; domain=.passport.weibo.com')
>>> cookie
<SimpleCookie: >
>>> cookie.load('SRF=155......; expires=Sun, 15-Apr-2029 13:18:56 GMT; path=/; domain=.passport.weibo.com')
>>> cookie
<SimpleCookie: SRF='155......'>
我的解决方法是在脚本开头用黑科技把这个正则改了,不过不保证可移植性,如果不能用就自己想办法吧
import http.cookies
http.cookies.BaseCookie._BaseCookie__parse_string.__defaults__ = (re.compile(r"""\s* # Optional whitespace at start of cookie(?P<key> # Start of group 'key'[""" + http.cookies._LegalKeyChars + r"""]+? # Any word of at least one letter) # End of group 'key'( # Optional group: there may not be a value.\s*=\s* # Equal Sign(?P<val> # Start of group 'val'"(?:[^\\"]|\\.)*" # Any doublequoted string| # or\w{3,},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT # Special case for "expires" attr| # or[""" + http.cookies._LegalValueChars + r"""]* # Any word or empty string) # End of group 'val')? # End of optional value group\s* # Any number of spaces.(\s+|;|$) # Ending either at space, semicolon, or EOS.""", re.ASCII | re.VERBOSE), # re.ASCII may be removed if safe.
)
跨域广播之后
广播完成后脚本跳转到https://passport.weibo.com/wbsso/login
,然后通常会重定向到https://weibo.com/ajaxlogin.php
,redirect
是下一个跳转地址
<html><head><script language='javascript'>parent.sinaSSOController.feedBackUrlCallBack({"result":true,"userinfo":{"uniqueid":"......","userid":null,"displayname":null,"userdomain":"?wvr=5&lf=reg"},"redirect":"https:\/\/weibo.com\/nguide\/interest"});</script></head><body></body></html>
__handle_login_page
中对这个页面的处理如下
# 调用parent.sinaSSOController.feedBackUrlCallBack跳转到weibo.com/nguide/interestelif url.startswith('https://weibo.com/ajaxlogin.php'):res_ = self.__get_jsonp_response(res)next_url = res_['redirect']
然后经过一堆重定向到你的微博主页https://weibo.com/....../home
恢复session
24小时后session会失效,此时再访问微博首页会被重定向到https://login.sina.com.cn/sso/login.php
,之后按登录流程处理即可
async def restore_session(self):async with self._session.get('https://weibo.com/') as r:return await self.__handle_login_page(str(r.url), await r.text())
有时候会重定向到新浪访客系统https://passport.weibo.com/visitor/visitor?a=enter
,这个页面的脚本也是没有混淆,带中文注释的。不过不管哪种方式最后都会到https://login.sina.com.cn/sso/login.php
# 新浪访客系统,用来恢复cookieelif url.startswith('https://passport.weibo.com/visitor/visitor'):if 'a=enter' in url:next_url = 'https://passport.weibo.com/visitor/visitor?a=restore&cb=restore_back&from=weibo'else:res_ = self.__get_jsonp_response(res)next_url = (f'https://login.sina.com.cn/sso/login.php?entry=sso&alt={res_["data"]["alt"]}'f'&returntype=META&gateway=1&savestate={res_["data"]["savestate"]}'f'&url=https%3A%2F%2Fweibo.com%2F%3Fdisplay%3D0%26retcode%3D6102')
微博登录和session恢复过程相关推荐
- 【49.Auth2.0认证与授权过程-微博开放平台认证授权过程-百度开放平台认证授权过程-社交登录实现(微博授权)-分布式Session问题与解决方案-SpringSession整合-Redis】
一.知识回顾 [0.三高商城系统的专题专栏都帮你整理好了,请点击这里!] [1-系统架构演进过程] [2-微服务系统架构需求] [3-高性能.高并发.高可用的三高商城系统项目介绍] [4-Linux云 ...
- python爬虫登录微博_为爬虫获取登录cookies: 使用Charles和requests模拟微博登录
上一节,我们讲了如何配置Charles代理,这一节我们通过模拟微博登录这个例子来看看如何使用Charles分析网站加载流程,顺便把微博模拟登录的Python代码也给实现了. 1. 用Charles记录 ...
- js调试微博登录案例
js调试 五.微博登录案例 1.分析流程 手动操作流程 访问首页https://weibo.com 输入用户名和密码 点击登录 如果有验证码,就输入验证码验证 成功跳转到微博首页面 请求流程分析过程 ...
- java加按钮_如何从零开始对接第三方登录(Java版):QQ登录和微博登录
阅读本文约需要8分钟 大家好,我是你们的导师,我每天都会在这里给大家分享一些干货内容(当然了,周末也要允许老师休息一下哈).上次老师跟大家分享了HashMap和TreeMap的知识,今天跟大家分享下对 ...
- oracle ora 00283,【案例】Oracle报错ORA-16433非归档丢失redo无法启动的恢复过程
天萃荷净 Oracle研究中心案例分析:运维DBA反映Oracle数据库处理非归档模式,redo文件损坏常规修复无法正常open数据库. 本站文章除注明转载外,均为本站原创: 转载自love wife ...
- 数据库startup报错_SQL Server数据库恢复过程内部–数据库STARTUP命令
数据库startup报错 A database recovery process is an essential requirement for database systems, It can be ...
- web app 第三方登录-微博登录(一)
在最近参与的一个android项目中,使用的是web app 的形式,就是android提供容器,但是里面的内容都由H5实现.由于不是原生的app,给集成第三方登录带来一些困难.下面把集成的过程分享下 ...
- 【航天信息开票软件V3.0金税盘版安装恢复过程】有坑有心得
@[TOC]航天信息开票软件V3.0金税盘版安装恢复过程 2023年5月11日 昨天下午我司财务打开"开票软件V3.0"提示更新,但是更新过程中出现错误.再启动 开票软件V3.0 ...
- 思科交换机的登录、密码恢复与应用
一.登录交换机 首先找一根CONSOLE线将计算机的串口与交换机的CONSOLE口相连.(注:CONSOLE[控制台]线的一端为RJ45的水晶头,一端用DB9的串口,如果想要自己制作这根线,可以使用一 ...
最新文章
- java验证码源码_Java通用验证码程序及应用示例(提供源码下载)
- Meta小冰英伟达一起搞事!亚洲首个元宇宙生态联合体来了
- TC工具后台模式_聊天能赚钱?来聊后台批量添加账号,伪装女性聊天赚钱内幕...
- JDBC事务--软件开发三层架构--ThreadLocal
- 观察者模式与职责链模式的相同和不同_GOF设计模式(策略模式,职责链模式)...
- linux-practice(23-24)
- 计算机组装与维修技能大赛视频,2013年计算机组装与维修技能大赛试题及答案真题...
- vmware workstation不可恢复错误:(vthread-7)
- Linux环境中的帮助命令有,Linux下的帮助命令
- java8调用unsafe_JDK8---UnSafe类实现CAS乐观锁
- Java、JSP报刊订阅管理系统的设计与实现
- 气候制度的转变和森林的丧失放大了亚马逊森林的火灾
- Pssp-mvirt: 基于多视图深度学习架构的肽二级结构预测
- 遗传算法之基因型与表现型的相互转换
- 在线教育未来的发展前景如何?
- KONG (API网关) 用CORS处理跨域,针对:非简单请求
- canvas实现一个线性图
- MM 供应商账户组后台配置步骤
- 在unity中读取并可视化dicom图像(fo-dicom / C# / unity)
- 浏览器渲染原理以及性能优化
热门文章
- SpringBoot 项目上传文件异常【java.io.IOException: Stream closed】
- (深度学习论文精读总结)You Only Look Once: Unified, Real-Time Object Detection
- ubuntu使用python读串口_21.python通过pyserial读写串口--2013-06-02
- C#ObjectArx Cad创建点线块
- 美国计算机硕士学校,美国计算机硕士不同学校申请难度大盘点(下篇)
- 转——解决游戏王DL的steam版锁区问题
- Oracle数据库实验4 Oracle数据库安全管理
- Java峰值和削峰_架构设计之流量削峰
- Android之集成极光推送
- 你给文字描述,AI艺术作画,精美无比!附源码,快来试试!