背景介绍
XXX项目性能测试中新增业务场景:XX设备的在线激活,因为存在多用户同时在线激活,故需进行性能测试以确认后台服务器系统在多用并发时功能是否正常,性能指标是否满足规格要求。用户使用场景为用户通过XX设备平台(类似客户端)触发激活请求,该请求经过中间系统处理并最终被Licnese后台服务器处理并响应。客户端与服务器经过了广域网环境,无设备在线激活业务操作界面。
场景和现状
XX设备平台通过http协议与中转系统进行交互,中转系统将http协议的消息转换为Web Service(SOAP)消息并转送给Licnese服务器进行处理,XX设备发出的http消息数据是经过加密处理的。已提供XX设备激活模拟工具(.exe文件+配置文件)和加解密dll文件/加解密jar包。.exe文件为win32控制台程序编写的模拟激活业务的工具,模拟工具执行时间很短,在几秒钟就完成激活业务(与XXX服务器发生五次交互),试图通过LR工具试录制脚本,发现无法录制到模拟工具发出的请求消息脚本。
方案确定
在LR中通过手工编写http协议脚本,在LR中模拟设备在线激活业务与中转系统交互,由于提供的加解密DLL文件并非C/C++语言写的,所以LR中选择http协议时无法直接调用加解密DLL,但因为提供了加解密jar包,可以在本地java环境中部署该jar包,在命令行中执行java命令来进行加解密操作,最终确定通过手工编写一个C的DLL,在该DLL中编写调用命令行并获取命令行结果的函数,在LR中加载并调用该DLL来实现数据的加解密, 另外,因为加解密后的数据为二进制数据,所以需要使用web_custom_request函数发送二进制消息体,如对二进制消息体的处理过程中需要使用循环,出于执行效率的考虑,可将这部分代码一并放入DLL中文件。
脚本
1 #ifndef _GLOBALS_H 2 #define _GLOBALS_H 3 4 //-------------------------------------------------------------------- 5 // Include Files 6 #include "lrun.h" 7 #include "web_api.h" 8 #include "lrw_custom_body.h" 9 10 //-------------------------------------------------------------------- 11 // Global Variables 12 //#define TESTDLL 0 13 14 //--------------------------------初始化-------------------------------- 15 //获取安全码的局部变量 16 char szSecurityCodeBody[8192]; //存放Body 17 char szPdtName[128]; //产品名称 18 char szPdtVer[128]; //产品版本号 19 char szDevESN[128]; //生成ESN,20-30位随机数字和字母 20 char szDevIndex[5]; //生成devIndex,设备ESN哈希后取前四个字节.... 21 char szSecurityCodBodyEnc[8192];//存放加密后的Body 22 char getSecurityCode_requestData[8192];//存放待解密data数据 23 char getSecurityCode_requestDataDnc[8192];//存放解密后的data数据 24 char vuserid_str[50]; //组装临时文件名 25 char curtime_str[50]; 26 char TmpFileName[100]; //临时文件名 27 int iRet = -1; //加解密函数返回值 28 int ContentLength = 0; 29 const char *SecurityCodeTou = "securityCode="; 30 char *SecurityCodeTmp = NULL; 31 const char *resCodeTou = "resCode="; 32 char *resCodeTmp = NULL; 33 int resCode = 0; 34 char *delim = "&"; 35 char requestDataDnc_Tmp[8192];//临时存放各响应解密后的data数据 36 37 //获取订单授权信息 38 char szAuthorizeBody[8192]; 39 char szOrdLac[128]; 40 char szAuthorizeBodyEnc[8192]; 41 char getAuthInfo_requestData[8192];//存放待解密data数据 42 char getAuthInfo_requestDataDnc[8192];//存放解密后的data数据 43 const char *authInfoTou = "authInfo="; 44 char *authInfoTmp = NULL; 45 46 //在线激活 47 char szActDevLicenseBody[8192]; 48 char szActDevLicenseBodyEnc[8192]; 49 char actDevLicense_requestData[8192];//存放待解密data数据 50 char actDevLicense_requestDataDnc[8192];//存放解密后的data数据 51 52 //在线下载 53 char szDownLoadOnlineBody[8192]; 54 char szDownLoadOnlineBodyEnc[8192]; 55 char getDevLicense_requestData[8192];//存放待解密data数据 56 char getDevLicense_requestDataDnc[8192];//存放解密后的data数据 57 58 //释放会话资源 59 char szReleaseSessionBody[8192]; 60 char szJsessionid[128]; 61 char szReleaseSessionBodyEnc[8192]; 62 char relSesRsr_requestData[8192];//存放待解密data数据 63 char relSesRsr_requestDataDnc[8192];//存放解密后的data数据 64 65 //文件内容校验 66 const char *ProductNameTou = "Product="; 67 char *ProductNameTmp = NULL; 68 char ProductNameTmp_STR[64]; 69 char *ProductName_delim = " "; 70 const char *VersionTou = "Version="; 71 char *VersionTmp = NULL; 72 char VersionTmp_STR[64]; 73 char *Version_delim = " "; 74 const char *EsnTou = "Esn=""; 75 char *EsnTmp = NULL; 76 char EsnTmp_STR[128]; 77 char *Esn_delim = "" "; 78 int strcmp_result = 0; //比较结果,相等为0 79 80 81 #endif // _GLOBALS_H
1 vuser_init() 2 { 3 4 int iLoadDllRes1 = -1; 5 6 7 //char szRes[4096] = {0}; //加密后的字符串,一定要定义足够大,防止越界!!! 8 //char szRes[4096] = "3d9d1defa4044f28e228b43de69b48ca9c992f974d184bc353905bee18d4890614eed06bce9a237da6a636043c456b3831e62ddf6ad7571487b38afc6a0ee1041b32f4ecf69c1d135f79e51ff71684132458d5d1935ddc8c700bf9552b06c80dd568cb4711a2d841674874d16570c3ac0efd5c8e2201e98788fdaa11763cf968f7b7b800655c26d3731fda05362ff59b6a9ec1caa8e06adf9db3900ef26c4dd898cc462f7597ee6800053e5748cc97584419b3f7b60a301bdb034701a9e97ee62749b1d9308deef976e1eaa103123ac2db17bc5e86545a6ad75711fc2442434fd0c9d365baf6267c12b070d1836b8e0e843c70232644a963a06a14357c78de0d"; 9 //int iRet = -1; 10 //char szRes2[4096] = {0}; //解密后的字符串 11 //char hello[100] = "hello"; 12 //char hello[100] = "version=1.0&reqType=getSecurityCode&prdName=USG5560&prdVer=V300R001&devIndex=CEA9"; 13 14 15 iLoadDllRes1 = lr_load_dll("dencdll.dll"); 16 if (0 != iLoadDllRes1) 17 { 18 lr_output_message("Notify:Load Dll error: dencdll.dll"); 19 return -1; 20 } 21 22 //----------------------------------------------测试加密---------------------------------------------- 23 /* 24 * 打印hello的加密结果 25 * 注意:1. SdpEndecTest文件夹、commons-codec-1.8.jar、libscpjavainterface.dll、log4j-1.2.15.jar、 26 * scpjavainterface.jar、SdpEndecApi.jar、vcgscpjavainterface.dll等均要放到“D:dmsdpsystemdll”目录下 27 * 函数原型: int Encrypt(int iType, const char* szSecurityCode, const char* szOri, const char* szFileName, char *szRes) 28 * iType: 类型 29 * szSecurityCode: 安全码 30 * szOri:需要被加密的字符串; 31 * szFileName:临时文件(建议一个用户创建一个); 32 * szRes: 加密后的字符串 33 * 34 */ 35 36 //iRet = Encrypt(0,"",hello,"D:\dm\sdp\LicenseLog\TmpFile\TmpFile1",szRes); 37 //lr_output_message("Notify:The result = %d, the encrypt are: %s",iRet,szRes); 38 39 // iRet = Decrypt(0,"",szRes,"D:\dm\sdp\LicenseLog\TmpFile\TmpFile2",szRes2); 40 // lr_output_message("Notify:The result = %d, the decrypt are: %s",iRet,szRes2); 41 42 return 0; 43 }
1 Action() 2 { 3 web_set_max_html_param_len("40960"); 4 5 START: 6 //--------------------------------初始化-------------------------------- 7 memset(szSecurityCodeBody, '