一、站点分析
MTime 时光网是一个电影媒体与电商服务平台,而这次做的模拟登录则是依靠其手机端站点,站点地址为:https://m.mtime.cn/#。切换到登录页面,再分别输入账号和错误的密码,点击登录,登录失败,截图如下:
很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
QQ群:1097524789
打开开发者工具, 选择“Network”,切换到“XHR”选项,找到一条名为 login.api 的请求,打开后可以发现就是登录所发送的请求,再查看该请求的参数部分,截图如下:
二、参数破解
1.参数分析
经过前面的分析可知有五个参数需要获取,分别是 t、name、password、code 和 codeId,其中 code 和 codeId 目前看来是空的,无须处理,而 name 就是输入的手机号,password 应该是输入的密码加密后的结果,剩下一个 t 还不知道是什么含义。
2.参数获取
在开发者工具中,Ctrl + F 全局搜索“password”,找到如下的 JavaScript 文件:
https://static3.mtime.cn/html5/20200116143308/js/views/member/signin.js
打开该文件后搜索“password”,首先是获取 name 属性为“password”的输入框,在下文中还发现了 vcode 和 vcodeId,这两个就是后面请求所需的 code 和 vcode 参数的值,截图如下:
继续搜索“password”,可以找到一个 getPassword() 方法,用于获取输入的密码内容,截图如下:
接着搜索“password”,找到如下内容:
这就是登录请求时的参数部分,其中密码 password 是将输入的密码进行加密后的结果,使用的是 f.desEcbPkcs7 方法,那这个方法具体是什么呢?
3.加密方法
在上面的 JS 文件中的 217 行打上断点,然后刷新页面并重新登录,页面会进入 debugger 模式,然后选中 desEcbPkcs7 部分,点击后跳转到 app.all.min.js 中的如下代码部分:
这个 af 函数就是加密方法了,其中用到了一个变量 CryptoJS,要获取这个变量的定义,就在上面代码中的1033行打上断点,再重新登录一遍,定位到 CryptoJS 的定义部分,截图如下:
对于变量 CryptoJS 的定义包含在 libs.all.min.js 中,但这个文件中的代码量比较大,若全部复制下来使用会不方便,而我们也只需要得到对变量 CryptoJS 进行定义的代码就够了,所以建议先把该 JS 文件保存到本地,再用编辑器打开,就能很快地得到我们所需要的代码了,即使如此还是有一千四百多行(汗~)。
得到了加密代码之后,我们只需要使用 execjs 进行编译和调用就可以了,使用方法可以参考上一篇博客。
三、模拟登录
通过前面的步骤,我们已经能够得到登录所需要的参数了,编写好加密方法之后,可以使用 Postman 进行测试,下面是用 Postman 进行登录的 POST 请求的响应结果:
从图中可以看到,返回的是一个 JSON 文件,其中包含了登录请求是否成功、登录的结果信息和用户信息等内容。 下面就是使用 Python 编写的模拟登录时光网的代码:
1 """ 2 Version: Python3.7 3 Author: OniOn 4 Site: http://www.cnblogs.com/TM0831/ 5 Time: 2020/7/5 14:19 6 """ 7 import execjs 8 import requests 9 10 11 class MTimeSpider: 12 def __init__(self, username, password): 13 self.username = username 14 self.password = password 15 16 def encrypted(self): 17 """ 18 use JavaScript to encrypt the password 19 :return: 20 """ 21 with open("encrypt.js", "r", encoding="utf-8") as f: 22 ctx = execjs.compile(f.read()) 23 self.password = ctx.call("encrypt", self.password) 24 25 def request(self): 26 """ 27 send request and get the response 28 :return: 29 """ 30 self.encrypted() 31 login_api = "https://m.mtime.cn/Service/callback-comm.mi/user/login.api" 32 data = { 33 "t": "20207515574379774", 34 "name": self.username, 35 "password": self.password, 36 "code": "", 37 "codeId": "" 38 } 39 res = requests.post(url=login_api, data=data) 40 status, msg = res.json()["data"]["status"], res.json()["data"]["msg"] 41 # print(status, msg) 42 if status == 1: 43 name = res.json()["data"]["user"]["nickname"] 44 print("用户: {} 登录成功!".format(name)) 45 else: 46 print("登录失败!{}".format(msg)) 47 48 49 if __name__ == '__main__': 50 print("请输入账号:") 51 usr = input() 52 print("请输入密码:") 53 pwd = input() 54 spider = MTimeSpider(usr, pwd) 55 spider.request()
运行后的截图如下: