Postman 加密接口测试 | 使用Rsa、Aes对参数加密

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Postman 加密接口测试 | 使用Rsa、Aes对参数加密

说句废话,以前都是笑别人接手看到什么xxxx代码,轮到自己看到了就是真的笑不出啦....

前言

做接口加密的测试也是上次遇到的,在这之前,都是在浏览器登录后,从请求头中复制 token 过来测试....

说真的,一瞬间我都有点诧异,这样也太麻烦了吧~,因而也就产生了这篇文章。

还有一些问题:

  1. postman 有内置加密Api,但不支持RSA加解密码。 (引入其他的js文件至环境变量,利用eval 函数进行解析,还可以利用request获取,将其保存至全局变量中)
  2. postman 中 request对象属性皆为只读,如何把提交时的明文变为密文? (前置脚本)

我先说说本次文章最终要实现的效果,以给大家一个阅读的参考。

目标:在测试登录接口时,针对登录接口需要用到的 username、password进行加密(加密方式分别为 rsa、aes ),再将加密后的数据传输给后端。

方法都是相似的,知道如何加密,其他的接口和字段都是差不多的实现方式。

一、Postman

对于Postman,对于这个工具,我认为是大都数小伙伴都要会的一个工具~,只是学习的程度的不同罢了

大致就是分为:

1、刚学的我们,就是用来测试一些基本接口

2、用了一段时间的我们,知道了有环境变量、集合操作等

3、了解到 postman 中可以结合Js文件对请求做一些参数,断言等等

4、集合接口测试、编写测试用例、利用内置变量随机生成数据测试接口等

5、.......


今天用到的就是 Postman 中的前置脚本Pre-request Script

二、Pre-request Script 编写前置脚本

2.1、脚本执行顺序

说之前,先说说postman中脚本的执行顺序,这里贴一张官方的图 postman 官方文档

在 Postman 中,单个请求的脚本执行顺序如下所示:

  • 与请求关联的预请求脚本将在发送请求之前执行
  • 与请求关联的测试脚本将在请求发送后执行

image.png

在发起request请求前,会先执行前置脚本,收到接口返回结果后,再执行 test script

2.2、准备测试接口信息

准备一个后端请求接口,能接收请求参数即可,我采取的是将加密的信息打印

测试接口信息

http://localhost:8080/login

 {
     "username":"{{rsa:username}}",
     "password":"{{esc:password}}"
 }

补充:用双层大括号包裹的参数,是引用postman的环境变量,做到动态可变

参数名前的:rsa,aes是为了测试多种加密方式给加的判断依据。

image.png

(图片说明:增加一个接口,填入基本信息)

2.3、Postman设置环境变量

这两处我们都需要用到~

image.png

接口用到的数据,一般是存放在某一个环境变量中,

如果很多处用到,一般可以考虑放到全局变量中了~

我们将rsa:username、aes:password放到一个环境变量中,这个环境变量的名称的就叫login

点击上图中的add即可

image.png

(图片说明:记得 ctrl + s 保存噢,手误:esc应为aes

另外我们用全局变量来保存一下 rsa的公钥,我这里的公私钥都是拿工具直接生成的 工具链接

image.png

将公钥保存在postman的全局变量中

image.png

另外全局变量之后我们用要来保存用来加密的 js 文件,不过这一步是利用前置脚本做的。

下载forge


 git clone https://github.com/digitalbazaar/forge.git
 cd forge文件夹下
 npm install

image.png

这样就算安装完了,否则会一直报没有找到 forge 对象

2.4、编写前置脚本

我们今天编写前置脚本的作用,就是给接口的参数进行加密,

所以最简单的方式,

  1. 拿到js文件,
  2. 运行
  3. 将参数进行加密
 // ------ 导入RSA ------
 if(!pm.globals.has("forgeJS")){
   pm.sendRequest("https://raw.githubusercontent.com/loveiset/RSAForPostman/master/forge.js", (err, res) => {
     if (!err) {
         // 保存至全局变量中,forgeJs 为 key,res.text() 为value值
         pm.globals.set("forgeJS", res.text())
     }
 })}
 ​
 // 这个函数前端的小伙伴应该比较了解
 // 它的作用是把对应的字符串解析成js代码并运行(将json的字符串解析成为JSON对象);
 eval(postman.getGlobalVariable("forgeJS"));
 ​
 // ------------ AES 加密 ------------
 function aesEncrypt(content){
     const key = CryptoJS.enc.Utf8.parse("Y5MUIOM7BUWI7BQR");
     const iv = CryptoJS.enc.Utf8.parse('S41AXIPFRFVJL73Z');
     const encrypted = CryptoJS.AES.encrypt(content, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7});
     return encrypted.toString();
 }
 ​
 // ------------ RSA 加密 ------------
 function rsaEncrypt(content){
     const pubKey = postman.getGlobalVariable("RSA_Public_Key");
     if(pubKey){
         const publicKey = forge.pki.publicKeyFromPem(pubKey);
         const encryptedText = forge.util.encode64(
             publicKey.encrypt(content, 'RSAES-PKCS1-V1_5', {
               md: forge.md.sha1.create(),
               mgf: forge.mgf.mgf1.create(forge.md.sha1.create())
         }));
         return encryptedText;
     }
 }
 pm.environment.set("rsa:username", aesEncrypt("nzc_wyh"));
  pm.environment.set("aes:password", rsaEncrypt("123456"));

我后端的接口返回数据就是将加密的数据直接放回~

这种方式接口的测试结果~

image.png

运行完查看环境变量和全局全量的变化

image.png

思考:但是你能感觉到这个前置脚本存在的问题吗?

如果同一个请求中有多个参数要进行加密,那我们岂不是要写多次set,这显然是不合理的,下面就做一个改善

当然如果不会的话,我们可以一起请教前端小伙伴,以让代码更加完善。

2.5 、优化前置脚本

 // ------ 通用方法 ------
 // 提取{{}}中内容
 function getBracketStr(text) {
     let result = ''
     let regex = /{{(.+?)}}/g;
     let options = text.match(regex);
     if (options && options.length > 0) {
         let option = options[0];
         if (option) {
             result = option.substring(2, option.length - 2)
         }
     }
     return result
 }
 ​
 ​
 // ------ 导入RSA ------
 if(!pm.globals.has("forgeJS")){
   pm.sendRequest("https://raw.githubusercontent.com/loveiset/RSAForPostman/master/forge.js", (err, res) => {
     if (!err) {
         // 保存至全局变量中,forgeJs 为 key,res.text() 为value值
         pm.globals.set("forgeJS", res.text())
     }
 })}
 ​
 // 这个函数前端的小伙伴应该比较了解
 // 它的作用是把对应的字符串解析成js代码并运行(将json的字符串解析成为JSON对象);
 eval(postman.getGlobalVariable("forgeJS"));
 ​
 // ------------ AES 加密 ------------
 function aesEncrypt(content){
     const key = CryptoJS.enc.Utf8.parse("Y5MUIOM7BUWI7BQR");
     const iv = CryptoJS.enc.Utf8.parse('S41AXIPFRFVJL73Z');
     const encrypted = CryptoJS.AES.encrypt(content, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7});
     return encrypted.toString();
 }
 ​
 ​
 // ------------ RSA 加密 ------------
 function rsaEncrypt(content){
     const pubKey = postman.getGlobalVariable("RSA_Public_Key");
     if(pubKey){
         const publicKey = forge.pki.publicKeyFromPem(pubKey);
         const encryptedText = forge.util.encode64(
             publicKey.encrypt(content, 'RSAES-PKCS1-V1_5', {
               md: forge.md.sha1.create(),
               mgf: forge.mgf.mgf1.create(forge.md.sha1.create())
         }));
         return encryptedText;
     }
 }
 // 获取当前请求中的加密变量 这里判断为字符串的原因是,
 // 我们引用环境变量时,一定是"{{}}" 这种格式的
 let requestData; 
 if((typeof request.data) === 'string'){
     requestData = JSON.parse(request.data)
 } else {
     requestData = request.data;
 }
 ​
 // Object.assign 拷贝对象 将request.headers 中的所有数据,拷贝到 requestData中
 requestData = Object.assign(requestData, request.headers);
 ​
 // 遍历
 Object.keys(requestData).map(key => {
      // 内容
     let value = requestData[key] + '';
     // 是否为变量
     if (value.indexOf('{{') !== -1) { 
         let content = getBracketStr(value);
         // 判断用是否加密,加密的话又是用哪种方式加密
         if (content.indexOf('aes:') !== -1) {
             let c = content.split('aes:')[1];
             let encryptedContent = pm.environment.get(c); // 加密内容
             encryptedContent = encryptedContent ? encryptedContent : c;
             pm.environment.set(content, aesEncrypt(encryptedContent));
         } else if (content.indexOf('rsa:') !== -1) {
             let c = content.split('rsa:')[1];
             let encryptedContent = pm.environment.get(c); // 加密内容
             encryptedContent = encryptedContent ? encryptedContent : c;
             pm.environment.set(content, rsaEncrypt(encryptedContent));
         }
     }
 });
 ​

优点

  1. 如果同一个请求中有多个参数加密,不用手动set,而是通过循环全部set进去
  2. 可以使用多种加密方式,只要继续扩展即可
  3. 扩展性更高

测试结果:

image.png

后记

小小一篇文章,希望给大家一点点帮助~


目录
相关文章
|
5天前
|
数据可视化 前端开发 测试技术
接口测试新选择:Postman替代方案全解析
在软件开发中,接口测试工具至关重要。Postman长期占据主导地位,但随着国产工具的崛起,越来越多开发者转向更适合中国市场的替代方案——Apifox。它不仅支持中英文切换、完全免费不限人数,还具备强大的可视化操作、自动生成文档和API调试功能,极大简化了开发流程。
|
5天前
|
存储 测试技术 数据库
接口测试工具攻略:轻松掌握测试技巧
在互联网快速发展的今天,软件系统的复杂性不断增加,接口测试工具成为确保系统稳定性的关键。它如同“翻译官”,模拟请求、解析响应、验证结果、测试性能并支持自动化测试,确保不同系统间信息传递的准确性和完整性。通过Apifox等工具,设计和执行测试用例更加便捷高效。接口测试是保障系统稳定运行的第一道防线。
|
5天前
|
Web App开发 JSON 测试技术
API测试工具集合:让接口测试更简单高效
在当今软件开发领域,接口测试工具如Postman、Apifox、Swagger等成为确保API正确性、性能和可靠性的关键。Postman全球闻名但高级功能需付费,Apifox则集成了API文档、调试、Mock与自动化测试,简化工作流并提高团队协作效率,特别适合国内用户。Swagger自动生成文档,YApi开源但功能逐渐落后,Insomnia界面简洁却缺乏团队协作支持,Paw仅限Mac系统。综合来看,Apifox是国内用户的理想选择,提供中文界面和免费高效的功能。
|
1月前
|
监控 JavaScript 测试技术
postman接口测试工具详解
Postman是一个功能强大且易于使用的API测试工具。通过详细的介绍和实际示例,本文展示了Postman在API测试中的各种应用。无论是简单的请求发送,还是复杂的自动化测试和持续集成,Postman都提供了丰富的功能来满足用户的需求。希望本文能帮助您更好地理解和使用Postman,提高API测试的效率和质量。
104 11
|
2月前
|
安全 应用服务中间件 网络安全
如何测试Nginx反向代理实现SSL加密访问的配置是否正确?
如何测试Nginx反向代理实现SSL加密访问的配置是否正确?
127 3
|
2月前
|
JavaScript 前端开发 测试技术
Postman 如何进行性能测试?
Postman 如何进行性能测试?
192 1
|
2月前
|
JSON Java 测试技术
SpringCloud2023实战之接口服务测试工具SpringBootTest
SpringBootTest同时集成了JUnit Jupiter、AssertJ、Hamcrest测试辅助库,使得更容易编写但愿测试代码。
83 3
|
3月前
|
机器学习/深度学习 弹性计算 自然语言处理
前端大模型应用笔记(二):最新llama3.2小参数版本1B的古董机测试 - 支持128K上下文,表现优异,和移动端更配
llama3.1支持128K上下文,6万字+输入,适用于多种场景。模型能力超出预期,但处理中文时需加中英翻译。测试显示,其英文支持较好,中文则需改进。llama3.2 1B参数量小,适合移动端和资源受限环境,可在阿里云2vCPU和4G ECS上运行。
173 1
|
3月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
95 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
使用postman测试接口时需要先登录怎么办
使用postman测试接口时需要先登录怎么办
3046 0
使用postman测试接口时需要先登录怎么办