在使用LoadRunner时,当你录制完脚本后可能会发现在交互的数据中会存在密文,或者当拿到接口文档时就已经明确的描述出了交互数据的加解密方法,你该怎么办?

事实上这样的遭遇如今已经成为了一种常态,发送数据或接收到的数据中很难避免不出现密文,有些加密算法是自定义的方法,有些则是标准的对称或非对称加密算法。

很多时候对于像JMeter这样原生的Java程序测试工具来说,在高级语言特性、丰富的加解密算法库条件下,你可能一个简单的BeanShell处理器或自定义函数就可以轻松解决这些问题,但对于LoadRunner这种原生是C语言脚本的测试工具来说,为了能够发挥其自身在性能上巨大的优势,可能处理起来就没有那么轻松。

你将采取的方案
首先你要清楚选择LoadRunner作为性能测试工具的主要目的是什么?在JMeter、nGrinder等开源工具不断发展壮大,并且各自特点鲜明,不断蚕食着LoadRunner的优势地位,大有后来居上的情况下,你仍然甘愿花费重金或冒着侵权风险的条件下使用LoadRunner时,你必须清楚LoadRunner能够为你带来什么。

LoadRunner能成为行业标杆的前提是其优越的自身性能和丰富的协议支持。因此,你在使用它时也有必要将这两方面发挥到极致。一些建议是尽量避免使用LoadRunner的Java或C#.Net脚本,这样做会严重影响工具自身的性能,导致LoadRunner失去其巨大的性能优势,这也意味着在很大程度上就失去了使用它的价值。

下面我们按解决问题方案的优先级进行罗列:

方案一是使用C语言实现加解密过程,唯一麻烦的是LR在内存控制方面可能有一些小问题需要自己调试一下;

方案二是用Java这样可以支持long类型的语言编写一个外部的接口实现计算,可以在需要计算时使用一个HTTP请求这个接口;

方案三是使用参数,本地代码计算与用户对应形成加密数据的参数列表;

方案四才是使用Java脚本;

当然最后方案五是找开发改逻辑。

案例
曾经在群里就遇到了这样一个发送端数据加密传输的需求:
9位数字,比如987654321,前缀123,后缀456,组合成一个13位的数字123987654321456,之后乘以数字30,再进行base64编码计算。

方案一实现
这个需求对于Java语言来说简直小儿科,只需要引入org.apache.commons.codec参考以下代码:

long number = 987654321L;
number = Long.valueOf("123" + String.valueOf(number) + "456") * 30;
String token = new String(Base64.encodeBase64(String.valueOf(number).getBytes()));
System.out.println(token);
1
2
3
4
但对于LoadRunner下的C语言脚本,就需要稍微转动一下脑筋来实现这样的需求:

const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

Action()
{
char *a = "123987654321456";
char base64[4096];
char bigint[16];
bigint_muti(a, 30, bigint);
base64_encode(bigint, base64, sizeof(char) * 16);
lr_output_message("%s", base64);
return 0;
}

char *
get_bigint(const int high_bit, const int low_bit){
//内存区域分配大于8,否则high和low的内存会连在一起导致无法补0
char high[16];
char low[16];

char bigint[16];
int i = 8;

sprintf(high, "%d\0", high_bit);
sprintf(low, "%d\0", low_bit);

memset(bigint, '\0', sizeof(char) * 16);

//低位补0
if(strlen(low) < 8){
strcat(bigint, high);
for(i; i > strlen(low); i--){
strcat(bigint, "0");
}

strcat(bigint, low);

} else {
strcat(bigint, high);
strcat(bigint, low);
}

//尾部置0
if(high_bit < 10000000){
bigint[15] = 0;
} else {
bigint[16] = 0;
}

return bigint;
}

char *
bigint_add(char *a, char *b){
int a_length = strlen(a);
int b_length = strlen(b);
int a_high_bit, b_high_bit, a_low_bit, b_low_bit, low_total, high_total;
int a_high_length = a_length - 8;
int b_high_length = b_length - 8;
char a_high[8];
char b_high[8];
char a_low[8];
char b_low[8];
char bigint[16];
memset(a_high, '\0', sizeof(char) * 8);
memset(b_high, '\0', sizeof(char) * 8);
memset(a_low, '\0', sizeof(char) * 8);
memset(b_low, '\0', sizeof(char) * 8);
memset(bigint, '\0', sizeof(char) * 16);
strncpy(a_high, a, a_high_length);
strncpy(b_high, b, b_high_length);

a_high_bit = atoi(a_high);
b_high_bit = atoi(b_high);

a_low_bit = atoi(a + a_high_length);
b_low_bit = atoi(b + b_high_length);

low_total = a_low_bit + b_low_bit;

if(low_total > 99999999){
low_total = low_total % 100000000;
high_total = a_high_bit + b_high_bit + 1;
} else {
high_total = a_high_bit + b_high_bit;
}

return get_bigint(high_total, low_total);
}

void
bigint_muti(char *a, int b, char *bigint){
int i = 0;
strcpy(bigint, a);

for(i; i < (b - 1); i++){
strcpy(bigint, bigint_add(a, bigint));
}
return;

}
char *
base64_encode(const unsigned char * bindata, char *base64, int binlength){
int i, j;
unsigned char current;
lr_output_message("%s", bindata);
for ( i = 0, j = 0 ; i < binlength ; i += 3 )
{
current = (bindata[i] >> 2) ;
current &= (unsigned char)0x3F;
base64[j++] = base64char[(int)current];

current = ( (unsigned char)(bindata[i] << 4 ) ) & ( (unsigned char)0x30 ) ;
if ( i + 1 >= binlength )
{
base64[j++] = base64char[(int)current];
base64[j++] = '=';
base64[j++] = '=';
break;
}
current |= ( (unsigned char)(bindata[i+1] >> 4) ) & ( (unsigned char) 0x0F );
base64[j++] = base64char[(int)current];

current = ( (unsigned char)(bindata[i+1] << 2) ) & ( (unsigned char)0x3C ) ;
if ( i + 2 >= binlength )
{
base64[j++] = base64char[(int)current];
base64[j++] = '=';
break;
}
current |= ( (unsigned char)(bindata[i+2] >> 6) ) & ( (unsigned char) 0x03 );
base64[j++] = base64char[(int)current];

current = ( (unsigned char)bindata[i+2] ) & ( (unsigned char)0x3F ) ;
base64[j++] = base64char[(int)current];
}
base64[j] = '\0';
return base64;
}

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

需要自己编写一个简单的大数加法(而且可以不普适实现),base64的C算法网上到处是,唯一麻烦的是LR在内存控制方面可能有一些小问题需要自己调试一下;

方案二实现
构建一个平行的Mock服务,几乎没有太多编码基础的测试工程师也可以通过NodeJS构建出一个加密计算的HTTP服务,参考如下代码:

const express = require('express');
const app = express();

app.get('/', function (req, res) {
if(req.query.number){
var number = req.query.number;
number = parseInt('123' + number + '456') * 30;
var token = (new Buffer(number.toString())).toString('base64');
res.send(JSON.stringify({
"token" : token
}));
} else {
res.send(JSON.stringify({
"status" : 500
}));
}

})

app.listen(80);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

于是可以通过请求该URL并将返回结果进行关联,便可以简单的将参数token进行赋值。
---------------------

LoadRunner中遭遇交互数据加密的处理方案的更多相关文章

  1. 前后端API交互数据加密——AES与RSA混合加密完整实例

    前言 前段时间看到一篇文章讲如何保证API调用时数据的安全性(传送门:https://blog.csdn.net/ityouknow/article/details/80603617),文中讲到利用R ...

  2. Redis 中常见的集群部署方案

    Redis 的高可用集群 前言 几种常用的集群方案 主从集群模式 全量同步 增量同步 哨兵机制 什么是哨兵机制 如何保证选主的准确性 如何选主 选举主节点的规则 哨兵进行主节点切换 切片集群 Redi ...

  3. 在.NET Core中遭遇循环依赖问题"A circular dependency was detected"

    今天在将一个项目迁移至ASP.NET Core的过程中遭遇一个循环依赖问题,错误信息如下: A circular dependency was detected for the service of ...

  4. js中getBoundingClientRect的作用及兼容方案

    js中getBoundingClientRect的作用及兼容方案 1.getBoundingClientRect的作用 getBoundingClientRect用于获取某个html元素相对于视窗的位 ...

  5. Loadrunner中web_find和web_reg_find函数的使用与区别

    总结一下Loadrunner中的检查点函数,主要介绍两个函数:web_find()和web_reg_find():这两个函数均用于内容的查找,但两者也有本质的区别,具体介绍如下:一.web_find( ...

  6. 0930MySQL中实现高性能高并发计数器方案(例如文章点击数)

    转自http://www.jb51.net/article/56656.htm 这篇文章主要介绍了MySQL中实现高性能高并发计数器方案,本文中的计数器是指如文章的点击数.喜欢数.浏览次数等,需要的朋 ...

  7. Loadrunner中Throughput(吞吐量)的分析与计算

    Throughput翻译为吞吐量,按照常规理解网络吞吐量表示在单位时间内通过网卡数据量之和,其中即包括本机网卡发送出去的数据量也包括本机网卡接收到的数据量,但这个理解在Loadrunner记录的Thr ...

  8. LoadRunner中循环操作

    Action() {     //Loadrunner中的FOR,WHILE,DO 循环语句 int i;   int whileloop = 1;   //FOR 循环   for (i=1;i&l ...

  9. 深入理解Loadrunner中的Browser Emulation

    深入理解Loadrunner中的Browser Emulation 深入理解Loadrunner中的Browser Emulation 3E?']V'VgB5n*S0一:基本介绍51Testing软件 ...

随机推荐

  1. hdu_1041_Computer Transformation_201311051648

    Computer Transformation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/ ...

  2. MYSQL 运维

    http://www.eimhe.com/thread-142990-1-1.html http://www.eimhe.com/search.php?mod=forum&searchid=6 ...

  3. Swift和Objective-C混合编程——Swift调用OC

    在iOS应用的开发中.Swift必将代替OC,两者的趋势是"短期共存,长期代替".但曾经有太多的代码是用OC语言完毕的,而Swift的开发也从 OC中继承了非常多的特性.两者也是有 ...

  4. CSS之实现二级菜单动态出现

    一直觉得二级菜单的出现效果仅仅有js才干控制.今天研究了一下阿里巴巴站点的首页,才发现,原来二级菜单的动态显示也能够使用CSS来控制,原来对CSS是静态的东西一直是误解它了,CSS也能够实现动态的效果 ...

  5. AOP代理分析

    一:代理 代理类和目标类实现了同样的接口.同样的方法. 假设採用工厂模式和配置文件的方式进行管理,则不须要改动client程序.在配置文件里配置使用目标类还是代理类,这样以后就非常easy切换.(比如 ...

  6. zoj2676 Network Wars(0-1分数规划,最大流模板)

    Network Wars 07年胡伯涛的论文上的题:http://wenku.baidu.com/view/87ecda38376baf1ffc4fad25.html 代码: #include < ...

  7. ios 导航栏(自己定义和使用系统方式)

    系统方式: //1.设置导航栏背景图片 [self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] ini ...

  8. vbs use

    VBScript中SendKeys的妙用 标签: vbscriptbasicmicrosoftinsertdeletestring 2011-05-26 15:29 1830人阅读 评论(0) 收藏  ...

  9. nginx+tomcat反复请求

    好久不写技术文章了,越发的认为单纯的讲技术没啥意思.怪不得知乎越来越火.由于大家都喜欢看故事.不喜欢硬生生的技术文章.笔者今天就来就给大家讲故事:) 近期站点压力突然增大,把带宽都占满了,訪问网页发现 ...

  10. STL_算法_逆转(reverse,reverse_copy)

    C++ Primer 学习中.. . 简单记录下我的学习过程 (代码为主) //全部容器适用 reverse(b,e)        //逆转区间数据 reverse_copy(b,e,b2) /** ...