背景
搞了那么久的自动化测试,灵机一动,可以在自动化项目里面加多一个功能:在自动化测试断言失败后自动向禅道提交 bug。以往都是测试结果直接输出,输出的形式目前暂定钉钉和测试报告,现在想要加多一个 bug 自动提交的功能。可以想象成自己有一个分身,她可以自己完成测试任务,测试过程中遇到 bug 就提交到禅道。岂不美哉~
问题
目前使用的禅道专业版本 10.4。看了禅道的登录接口,找到它的接口参数如下:
1
2
3
4
5
6
7
8
9
10
11
12
Request URL: http://localhost:8080/zentao/user-login.html
Request Method: POST
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36
form-data
account: username
password: 95868bb5e73c6fb5ad280abf63fbsfg
referer: http://localhost:8080/zentao/bug-browse-14-0-openedbyme.html
verifyRand: 2010824780
form-data 里的 password 和 verifyRand ,可以看到前端在请求前均进行了加密。检查登录页面 http://localhost:8080/zentao/user-login.html 的源代码:
1
2
3
4
5
6
7
8
9
$(document).ready(function()
{
$('#verifyPassword').closest('form').find('#submit').click(function()
{
var password = $('input#verifyPassword').val().trim();
var rand = $('input#verifyRand').val();
$('input#verifyPassword').val(md5(md5(password) + rand));
});
});
由源代码可以看出,password 和 rand 均使用 md5 进行了加密,而接口的 verifyRand == rand。
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
import requests
import re
import hashlib
username = "username" # 登录账户
pw = "password" # 登录密码
base = "http://localhost:8080" # 服务地址
user = requests.Session()
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36"
}
class Zentao:
def __init__(self):
self.login_url = "%s/zentao/user-login.html" %base
self.product_url = "%s/zentao/product-index-no.json" %base
self.rand = None
self.pwd = None
self.product_id = None
def union_option(self):
self.get_rand()
self.get_password()
self.user_login()
self.check_login()
self.get_product_list("saas")
def get_rand(self):
'''获取 rand 值'''
while True:
res_rand = user.get(self.login_url, headers=headers)
# res_rand.encoding = 'utf-8'
# print("res_rand.text = %s" %res_rand.text)
rand = re.findall(r"'verifyRand' value='(.+?)'", res_rand.text)
# print("rand[0] = {}".format(rand[0]))
if len(rand[0]) == 10: # rand 的长度不固定可为9或10,判断长度为10时就不再请求登录页面接口
self.rand = rand[0]
break
print(self.rand)
def get_password(self):
'''获取 password'''
# 方式一
hash = hashlib.md5()
hash.update(pw.encode('utf-8'))
f = hash.hexdigest() + self.rand
# print("f = %s" %f)
# 方式二
hash2 = hashlib.md5(f.encode('utf-8'))
self.pwd = hash2.hexdigest()
print("pwd = %s" %self.pwd)
def user_login(self):
'''用户登录'''
data = {
"account": username,
"password": self.pwd,
"referer": "%s/zentao/bug-browse-14-0-openedbyme.html" %base,
"verifyRand": self.rand
}
res_login = user.post(self.login_url, headers=headers, data=data)
# res_login.encoding = 'utf-8'
# print("res_login.text = %s" %res_login.text)
def check_login(self):
'''检查登录'''
res_check = user.get("%s/zentao/bug-browse-14-0-openedbyme.html" %base, headers=headers)
# res_check.encoding = 'utf-8'
# print("res_check.text = %s" %res_check.text)
result = re.findall(r"\<a href=\'\/zentao\/user-logout.html' \>(.+?)\<\/a\>", res_check.text)
# print("result = {}".format(result))
if result[0] == "退出":
print("登录成功")
if __name__ == '__main__':
zentao = Zentao()
zentao.union_option()
运行结果:
1
2
3
1490976266
pwd = f6bddcc70263e1d26f946ca8e6f38970
登录成功