基础类封装-解决系统token刷新机制带来的token变更问题

背景:

当前测试系统token存在刷新机制,每隔20min刷新一个最新的token,当在接口测试过程中,长时间运行导致登录的token失效

刷新机制:登录系统后获取一个toekn_A,15min后刷新一个token_B,20min以内token_A和token_B都生效,20min后token_A失效,token_B生效(以此循环),故为此需要解决自动化测试过程中的token刷新机制

解决思路:

1.将登录后返回的token_A存放到测试环境的数据库中

2.主进程在运行过程中开启一个子线程去请求心跳接口,按心跳间隔获取最新的token_B信息,如果token_A等于token_B则不更新数据,反之则将最新的token_B存放到数据库中

  1 import os
  2 import sys
  3 sys.path.insert(0,os.getcwd())
  4 import time
  5 import json
  6 import threading
  7 from lib.tools import *
  8 from lib.mbh_init_db import *
  9 from lib.logger import logger
 10 from util.encry import md5_key
 11 from interface.tool import Tool
 12 from httprun.HttpRun import HttpRun
 13 from util.RandomStr import RandomStr
 14 from config.VarConfig import cert_file
 15 from config.golbalSetting import hostname,cmapi
 16 
 17 
 18 class CMAPI(threading.Thread):
 19 
 20     # 定义心跳间隔,单位s
 21     interval = 45
 22     # 定义域名信息
 23     domain = cmapi
 24     # 忽略SSL验证
 25     verify = False
 26     # 定义crt证书文件
 27     cert = cert_file
 28     # 定义操作终端
 29     sobeyhive_http_system = getattr(Tool,'sobeyhive_http_system')
 30     # 定义工具类型
 31     sobeyhive_http_tool = getattr(Tool,'sobeyhive_http_tool')
 32     # 定义site
 33     sobeyhive_http_site = getattr(Tool,'sobeyhive_http_site')
 34     # 定义user-agent
 35     user_agent = getattr(Tool,'user_agent')
 36     # 定义数据表的名称
 37     init_table = table_name
 38     # 定义日志
 39     logger = logger
 40 
 41     def __init__(self,username,password):
 42         threading.Thread.__init__(self) # 定义继承类初始化方法
 43         self.username = username
 44         self.password = password
 45         self.httprun = HttpRun().http_run
 46         self.db = initDB()
 47         self.logoutflag = False  # 设置登出标记
 48         self.validuser = False   # 设置用户是否有效
 49         # 定义用户信息
 50         self.logininfoid = None  # 心跳维护使用
 51         self.loginip = None  # 登录ip
 52         self.loginname = None  # 登录用户名
 53         self.sitecode = None  # 多站点
 54         self.usercode = None
 55         self.userid = None
 56         self.usertoken = None
 57         self.organizationcode = None
 58         self.refreshtoken = None  # 定义刷新的totkn,从子线程中获取
 59         # cookies
 60         self.cookies = None
 61 
 62     def login(self):
 63         """
 64         login
 65         :return dict type
 66         """
 67         self.logger.logger.info('当前方法: %s'%p.get_current_function_name())
 68         url = self.domain + "/CMApi/api/basic/account/login"
 69         self.logger.logger.info('请求地址: %s' % url)
 70         headers = {
 71             "Content-Type": "application/json"
 72         }
 73         self.logger.logger.info('请求头: %s' % headers)
 74         passwd = md5_key(self.password) if self.password else None
 75         playload = {
 76             "LOGINNAME": self.username,
 77             "LOGINPWD": passwd,
 78             "LOGINSUBSYSTEM": self.sobeyhive_http_system['WEBCM'],
 79             "LOGINIP": RandomStr.generate_uuid()
 80         }
 81         self.logger.logger.info('请求参数: %s' % playload)
 82         try:
 83             response = self.httprun(method='post', url=url, data=json.dumps(playload), headers=headers,verify=self.verify)
 84             if response is None:
 85                 sys.exit('login response is None,Please Check environment!')
 86             res = response.json()
 87             if res['code'] == '0':
 88                 setattr(self, 'logininfoid', res['ext']['logininfoid'])
 89                 setattr(self, 'loginip', res['ext']['loginip'])
 90                 setattr(self, 'loginname', res['ext']['loginname'])
 91                 setattr(self, 'sitecode', res['ext']['organizations'][0]['sitecode'])
 92                 setattr(self, 'usercode', res['ext']['usercode'])
 93                 setattr(self, 'userid', res['ext']['userid'])
 94                 setattr(self, 'usertoken', res['ext']['usertoken'])
 95                 setattr(self, 'organizationcode', res['ext']['organizations'][0]['organizationcode'])
 96                 setattr(self, 'cookies', response.cookies)
 97                 # print(json.dumps(re,indent=2,ensure_ascii=False))
 98                 # 存储用户名及token,用户后续的心跳更新,先判断表中是否存在token,存在则更新,不存在则插入
 99                 query_sql = "select username from {0} where username = '{1}'".format(self.init_table,self.username)
100                 result = self.db.query_db(query_sql,state="all")
101                 if isinstance(result,tuple) and len(result)==0:
102                     insert_sql = "insert into {0} value('{1}','{2}');".format(self.init_table, self.loginname, self.usertoken)
103                     self.db.execute_db(insert_sql)
104                 else:
105                     if self.username in result[0].get('username'):
106                         updata_sql = "update {0} set usertoken = '{1}' where username='{2}'".format(self.init_table,self.usertoken,self.username)
107                         self.db.execute_db(updata_sql)
108             else:
109                 self.logger.logger.info('请求耗时: %s 毫秒' % (int(response.elapsed.microseconds) // 1000))
110                 self.logger.logger.error('登录失败,Status Code: %s'% response.status_code)
111                 return res
112         except Exception as e:
113             self.logger.logger.exception(e)
114             return None
115         else:
116             self.logger.logger.info('请求耗时: %s 毫秒'%(int(response.elapsed.microseconds)//1000))
117             self.logger.logger.info('响应结果: %s' % res)
118             self.validuser = True
119             return res
120 
121     def testfunctionpopedom(self):
122         """判断登录权限"""
123         self.logger.logger.info('当前方法: %s' % p.get_current_function_name())
124         if self.validuser:
125             usertoken = self.get_token()
126             url = self.domain + "/CMApi/api/basic/account/testfunctionpopedom?usertoken={0}".format(usertoken)
127             self.logger.logger.info('请求地址: %s' % url)
128             headers = {
129                 "Content-Type": "application/json",
130                 "sobeyhive-http-site": self.sitecode,
131                 "sobeyhive-http-system": CMAPI.sobeyhive_http_system['WEBCM'],
132                 "sobeyhive-http-token": usertoken,
133                 "sobeyhive-http-tool": CMAPI.sobeyhive_http_tool['WEBCM'],
134                 "sobeyhive-http-usercode": self.usercode
135             }
136             self.logger.logger.info('请求头: %s' % headers)
137             payload = [
138                 {
139                     "system":"WEBCM",
140                     "tool":"DEFAULT",
141                     "popedomname":"CANUSEWEBCM"
142                 }
143             ]
144             try:
145                 response = self.httprun('post', url, headers=headers, data=json.dumps(payload),verify=self.verify)
146                 res = response.json()
147             except Exception as e:
148                 self.logger.logger.exception(e)
149             else:
150                 self.logger.logger.info('请求耗时: %s 毫秒' % (int(response.elapsed.microseconds) // 1000))
151                 self.logger.logger.info('响应结果: %s' % res)
152                 return res
153         else:
154             return
155 
156     def heartbeat(self):
157         """
158         cmapi心跳接口
159         :return:
160         """
161         self.logger.logger.info('当前方法: %s' % p.get_current_function_name())
162         usertoken = self.get_token()
163         if self.validuser:
164             url = self.domain + "/CMApi/api/basic/account/heatbeat?loginInfoID={0}&systemtype=WEBCM".format(self.logininfoid)
165             self.logger.logger.info('请求地址: %s' % url)
166             headers = {
167                 "Content-Type": "application/json",
168                 "sobeyhive-http-site": self.sitecode,
169                 "sobeyhive-http-system": CMAPI.sobeyhive_http_system['WEBCM'],
170                 "sobeyhive-http-token": usertoken,
171                 "sobeyhive-http-tool": CMAPI.sobeyhive_http_tool['WEBCM'],
172                 "sobeyhive-http-usercode": self.usercode
173             }
174             self.logger.logger.info('请求头: %s' % headers)
175             try:
176                 response = self.httprun('get',url, headers=headers,verify=self.verify)
177                 res = response.json()
178                 if response.status_code == 200:
179                     pass
180                 else:
181                     self.logger.logger.error("requests failed! Status Code:", res.status_code)
182             except Exception as e:
183                 self.logger.logger.exception(e)
184             else:
185                 self.logger.logger.info('请求耗时: %s 毫秒' % (int(response.elapsed.microseconds) // 1000))
186                 self.logger.logger.info('响应结果: %s' % res)
187                 return res
188         else:
189             return
190 
191     def logout(self):
192         """
193         cmapi登出接口
194         :return:
195         """
196         self.logger.logger.info('当前方法: %s' % p.get_current_function_name())
197         url = self.domain + "/CMApi/api/basic/account/logout"
198         self.logger.logger.info('请求地址: %s' % url)
199         try:
200             response = self.httprun(method="get",url=url,verify=self.verify)
201             res = response.json()
202             self.logoutflag = True  # 设置登出标志
203             if res['code'] == "1":
204                 self.logger.logger.info("登出成功!")
205                 return True
206             else:
207                 return False
208         except Exception as e:
209             self.logger.logger.info('请求耗时: %s 毫秒' % (int(response.elapsed.microseconds) // 1000))
210             self.logger.logger.info('响应结果: %s' % res)
211             self.logger.logger.exception(e)
212 
213     def run(self):
214         """
215         开启子线程,按固定间隔获取最新token
216         :return:
217         """
218         while True:
219             if not self.logoutflag:
220                 # 设置心跳间隔
221                 time.sleep(self.interval)
222                 res = CMAPI.heartbeat(self)
223                 self.logger.logger.info(res)
224                 #TODO: 更新token到mysql中,先查询token值
225                 query_sql = "select usertoken from {0} where username = '{1}'".format(self.init_table,self.username)
226                 result = self.db.query_db(query_sql)
227                 if res['ext'] != '':
228                     if result[0].get('usertoken') != res['ext']:
229                         update_sql = "update {0} set usertoken = '{1}' where username='{2}'".format(self.init_table,res['ext'],self.username)
230                         self.db.execute_db(update_sql)
231                         self.refreshtoken = res['ext']
232                 else:
233                     self.logger.logger.error("token更新失败:",res)
234             else:
235                 break
236 
237     def get_token(self):
238         """获取用户的token信息"""
239         sql = "select usertoken from {0} where username = '{1}';".format(self.init_table, self.username)
240         self.db.select_db(db_name)
241         query_result = self.db.query_db(sql)
242         if query_result:
243             return query_result[0].get('usertoken')
244         else:
245             return None
246 
247 
248 
249 
250 
251 
252 
253 if __name__ == "__main__":
254     print("父进程PID:%s" % os.getpid())
255     t = CMAPI('tyw','tyw')
256     t.login()
257     t.start() # 开启子进程,当存在token刷新机制时开启
258     t.testfunctionpopedom()
259     # t.get_token()
260     t.logout()
原文地址:https://www.cnblogs.com/tython/p/12701546.html