一、站点分析
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 文件保存到本地,再用编辑器打开,就能很快地得到我们所需要的代码了,即使如此还是有一千四百多行(汗~)。
View Code
得到了加密代码之后,我们只需要使用 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()
运行后的截图如下:
