|
案例:通过协议模拟登录58同城
---
login url : https://passport.58.com/58/login/pc/dologin
观察了一下需要注意的参数有:
- username: 账号
- password: 加密(密码)
- token: 密文
password是密码加密后的定值,token是动态的。
ctrl+F搜索一下token值,找到了返回token的接口
可以观察出获取token的接口中, callback和path参数 跟时间戳有关
点击右侧的 Initiator , 点第一个 r 进去,打上断点,刷新页面
刷新之后可以看到,如下图所示
可以发现此处i中的callback参数是和t的值一样
往上找一找t是如何生成的
var t = e.jsonpCallback || "JsonpCallBack" + (new Date).getTime() + Math.floor(1e3 * Math.random())
既 t = "JsonpCallBack" + 时间戳 + 随机数
这里可以把js复制下来用execjs生成,也可以用python来模拟:
import math,time,random print("JsonpCallBack" + str(int(time.time()*1000)) + str(math.floor(1000*random.random())))
经过观察,path参数 "固定的url" + "13位时间戳"
接着可以来用代码构造下请求,获取token值
import math,random,time import requests pathtime = str(int(time.time() * 1000)) jsoncallback = "JsonpCallBack" + str(int(time.time() * 1000)) + str(math.floor(1000.0 * random.random())) url = "https://passport.58.com/58/login/init?source=58-homepage-pc&path=https%253A%252F%252Fbj.58.com%252F%253Fpts%253D{}&psdk-d=jsdk&psdk-v=1.0.6&callback=JsonpCallBack{}".format(pathtime,jsoncallback) headers = { 'referer': 'https://passport.58.com/login?path=https%3A%2F%2Fmy.58.com%2F', 'sec-fetch-dest': 'script', 'sec-fetch-mode': 'no-cors', 'sec-fetch-site': 'same-origin', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36', } print(requests.get(url,headers=headers).text)
打印出的结果中可以提取到token
JsonpCallBackJsonpCallBack1605081373854724({"code":0,"data":{"complainSwitch":true,"rememberSwitch":true,"token":"CJQM-Txgu-IiNWn-4F5Td-kJAgEPcHtd","action":"0"},"msg":"成功"})
其实拿到token后就可以完成模拟登录了,感兴趣的话可以一起再找一下登录密码是如何进行加密的。
还是先搜索参数位置,找到一个最像的
可以通过关键词password 搜到 n.encrypt,然后找到了这里,断点调试下
可以发现,e.password 就是我们输入的密码,n.encrypt 就是加密后的结果
所以点进去看一下
在该位置断点
e点进去可以发现
在生成i,o后,经过处理传递到 encryptString
encodeURIComponent(): 这里是 Native code 函数: 把字符串作为 URI 组件进行编码,(正常的密码可以不管)
rsaExponset 和 rsaModulus 这两个值直接复制出来,
r.rsaExponent = "010001"
r.rsaModulus = "008baf此处省略N多字40db74cb69f"
点击跳转到 encryptString 方法查看:
t和s已经有了,o可以在上面找到,时间戳+i,i=定值-时间戳
可是加密好像跟密码没有什么关系呀,回过头看了一下,才发现 o 在外层是和密码拼接了一下。
接下来组合上面的js,先把encryptString全部复制到一个js文件中,
然后定义一个方法传入参数来调用。
为了省空间,先把前面的改动贴出来,最后再放完整的代码。
function encryptString(pwd) { var ii = 1411093327735 - (new Date).getTime(); var o = (new Date).getTime() + ii; var i = o + pwd; var r = RSAUtils.getKeyPair("010001", "", "008baf14121377fc76eaf7794b8a8af17085628c3590df47e6534574efcfd81ef8635fcdc67d141c15f51649a89533df0db839331e30b8f8e4440ebf7ccbcc494f4ba18e9f492534b8aafc1b1057429ac851d3d9eb66e86fce1b04527c7b95a2431b07ea277cde2365876e2733325df04389a9d891c5d36b7bc752140db74cb69f"); return RSAUtils.encryptedString(r, i) } !function(e) { void 0 === e.RSAUtils && (e.RSAUtils = {}); //此处省略N行代码 //此处省略N行代码 RSAUtils.setMaxDigits(130) }(window);
把js复制到控制台测试一下,返回的结果和最初看到的一样,说明成功了
下面可以构筑完整的登录代码了
目前这里文章发布后不能修改,还是贴csdn的链接,后边有改动方便更新
博客地址: https://blog.csdn.net/weixin_43582101/article/details/109253299
输出的结果:
返回的response-header中,set-Cookie就是登录成功后服务端发放的cookie。
如果返回中没set-cookie的话,可能是你的账号风险程度较高,登录时需要验证码。
如果是图文验证码,可以想办法识别后,写入data的参数中,重新请求,
如果是向平台发短信验证的话,推荐换号吧。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|