在接口测试工具中配置动态签名的方法

2023-04-11  本文已影响0人  花生草

接口鉴权与动态签名概述

为了保证接口的安全性,通常都会加入客户端身份鉴权的机制。一种是基于cookie的身份验证,当测试这种接口时,常用方式是使用浏览器登陆后,调用Chrome的F12开发者工具,任意选取一个接口从标头中的Cookie复制粘贴到接口测试工具中,就可以快乐玩耍了。风险是根据服务器端的设置cookie可能在一段时间后过期,只要保持浏览器窗口活跃或者测试工具的使用状态,一般都不会对测试有太大影响。

image.png

另一种签名方式,是通过拼接每次请求里的参数再使用MD5算法生成签名,如果请求内容每次都不变,那么和第一种就没有本质区别,测试时sign设置一个固定的值就可以。但是当请求里含有可变参数,例如当前时间戳或者有随机生成的salt值时,每次请求的签名都会发生动态变化,那么可以按照本文介绍的设置动态签名通用思路进行配置。

接口功能、性能测试工具

签名的通用步骤

两款接口测试工具,功能测试代表ApiFox和性能测试代表Jmeter,配置动态签名的步骤。
针对每个请求计算签名的算法,基本上由两步组成,首先拼接出字符串,再对字符串签名。例如百度翻译签名算法
下面是一个简单的HTTP POST请求例子,假设拼接字符串的要求是将API和请求body中按照key:value拼接成一个字符串,第一步先拼接出字符串“api/open/testapi+appid123+param1CD+time123+密钥”。第二步对得到的字符串用MD5算法计算得到sign=9E47C32D0B70A398E1B7EBCBEC10F5FD

http://localhost/open/testapi
{
    "appid": "123",
    "time": "1681199355",
    "param1": "CD"
}

为了方便将签名应用在不同场景上,将上述算法写成一个外部程序进行调用,例如jar包,变量作为运行参数传入。以上面的请求为例,java -jar dynamic-sign.jar "/open/testapi" "{"appid":"123","time":"1681199355","param1":"CD"}"

为了方便打出一个包含外部依赖,可直接执行的jar包,在pom.xml使用下面maven-shade-plugin插件,mvn package就行了。执行java -jar时会执行主类中的main方法。

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>主类的full path</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

有了签名jar包后,在apifox和jmeter中配置略有区别

Apifox中配置签名

var queryParams = pm.request.url.query
var pathArray = pm.request.url.path
var path = pathArray.join('/')
var body = pm.request.body.raw
//预防body中有变量,达到取替换后的值的效果
body = pm.variables.replaceIn(body)
var timestamp = pm.environment.get("TIMESTAMP")
try{
    var jarResult = pm.execute('dynamic-sign.jar',[path, timestamp, body], { windowsEncoding: 'utf-8' })
    jarResult = jarResult.trim()
    console.log('output sign:'+jarResult)
    pm.environment.set("SIGN", jarResult);

}catch(e){
    console.error(e.message)
}

时间戳要求是当前时间,所以也需要添加一个获取当前时间的脚本。用js函数取得当前时间后,设置到环境变量中

var timestamp = new Date().getTime();
pm.environment.set("TIMESTAMP", timestamp);

Jmeter中配置签名

import com.test.util.MyEncrypt;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.Argument;

String timestamp = vars.get("TIMESTAMP").trim();
Arguments args = sampler.getArguments();
Argument arg = args.getArgument(0);
String body = arg.getValue().trim();
String path = sampler.getPath();
path = path.substring(1);

String sign = MyEncrypt.genSign(path, timestamp, body);
//log.info("sign:"+sign);
vars.put("SIGN", sign);

设置当前时间时,使用Jmeter的内置函数time如下图。使用时用${TIMESTAMP}


image.png

签名中可能遇到的坑

如果出现请求端发送的签名和服务端计算出的签名不一致,导致鉴权不通过,看看是否符合下面的坑

fastjson与gson

签名算法中间步骤可能会涉及字符串、JSON对象、Map对象的转换,对于简单结构{"a":"1"},签名结果没有区别。如果有数组{"a":["1"]}可能会签出不同的结果。下面的2种方案,挨个试试

//方案一
Map<String, Object> paramMap = new Gson().fromJson(bodyStr, Map.class);
//方案二
JSONObject body = JSONObject.parseObject(bodyStr);
body.forEach( (k,v) -> map.put(k, String.valueOf(v)));

数字

例如使用的参数是{"a":1}签名结果不正确,换成{"a":"1"}试试

Windows系统下斜杠/开头的路径

java -jar xx.jar "/open/apitest" 签名不正确,添加debug日志后发现实际传入的参数被加上了前缀类似C:/xxx/open/apitest。解决方法是参数中不传第一个斜杠java -jar xx.jar "open/apitest",在算法内部添加斜杠

总结

为请求配置动态签名的思路为

  1. 编译出可执行jar包
  2. 参考工具文档,获取当前请求的API/body等参数,作为jar包参数,来生成签名
  3. 将签名设置为全局变量,供请求发出的时候使用
上一篇 下一篇

猜你喜欢

热点阅读