在使用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. [luogu1156]垃圾陷阱_动态规划_背包dp

    垃圾陷阱 luogu-1156 题目大意:Holsteins在距离地面D英尺的地方,FJ间隔时间ti会往下扔第i个垃圾.Holsteins对待每一个垃圾都会选择吃掉或者垫高.Holsteins有10个 ...

  2. mongodb之配置

    前言 最新版本支持yaml格式的配置文件,只支持空格,不能使用tab 详细配置说明 #系统日志配置 systemLog: destination: file path: /var/log/mongod ...

  3. device busy

    在mount的时候经常会有device busy,这通常是因为该目录被某个用户或者进程使用.这时候可以用如下命令: fuser mount point 来看一下该mount point被哪个进程占用. ...

  4. vs2010+cuda5.0+qt4.8

    在进行CUDA处理的时候,总是在控制台程序下,于是就想要通过qt进行界面处理. 一开始先测试一下qt的环境,新建一个qt项目,不过在运行的时候提示平台不对,换成64位 出现 这个是qt的版本问题,在右 ...

  5. poj 3468 A Simple Problem with Integers(线段树+区间更新+区间求和)

    题目链接:id=3468http://">http://poj.org/problem? id=3468 A Simple Problem with Integers Time Lim ...

  6. 整理100道 .net面试题

    前段时间,我在准备面试的时搜到的一套 net开发人员面试题,感觉比较全面,一直保存在草稿,刚在整理后台时翻了出来,干脆就发出来好了,以备不时之需. 1. .NET和C#有什么区别 答:.NET一般指 ...

  7. uva 11605 - Lights inside a 3d Grid(概率)

    option=com_onlinejudge&Itemid=8&page=show_problem&problem=2652" style=""& ...

  8. mac os lscpu 【转】

    CPU Information on Linux and OS X This is small blog post detailing how to obtain information on you ...

  9. C++ 中的友元(friend)

    首先友元不是一个好的设计,它破坏了封装.并且自身有很多局限:比如友元关系不能被继承:友元关系是单向的,不具有交换性:友元关系不具有传递性. 类内声明的 friend 变量(或者函数)在访问该类的成员时 ...

  10. Genesis 多边形闭轮廓填充算法

    通过逐行扫描,计算得出直线与多边形相交点进行求解 原理图形如下所示: 相关函数: /// <summary> /// 求点P到线段L距离 /// </summary> /// ...