• 测试老鸟整理,Postman加密接口测试-Rsa/Aes对参数加密(详细总结)



    前言

    一些问题

    postman 有内置加密Api,但不支持RSA加解密码。 (引入其他的js文件至环境变量,利用eval 函数进行解析,还可以利用request获取,将其保存至全局变量中)

    postman 中 request对象属性皆为只读,如何把提交时的明文变为密文? (前置脚本)

    实现目标

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

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

    1、Postman工具

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

    大致就是分为:
    1)刚学的我们,就是用来测试一些基本接口
    2)用了一段时间的我们,知道了有环境变量、集合操作等
    3)了解到 postman 中可以结合Js文件对请求做一些参数,断言等等
    4)集合接口测试、编写测试用例、利用内置变量随机生成数据测试接口等
    5)…

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

    1)脚本执行顺序

    说之前,先说说postman中脚本的执行顺序,这里贴一张官方的图 postman 官方文档
    在 Postman 中,单个请求的脚本执行顺序如下所示:

    在这里插入图片描述

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

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

    2)准备测试接口信息

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

    测试接口信息:
    地址:http://localhost:8080/login

     {
         "username":"{{rsa:username}}",
         "password":"{{esc:password}}"
     }
    
    • 1
    • 2
    • 3
    • 4

    补充:用双层大括号包裹的参数,是引用postman的环境变量,做到动态可变
    参数名前的:rsa,aes是为了测试多种加密方式给加的判断依据。

    在这里插入图片描述

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

    3)Postman设置环境变量

    这两处都需要用到

    在这里插入图片描述

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

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

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

    点击上图中的add即可

    在这里插入图片描述

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

    另外用全局变量来保存一下 rsa的公钥,这里的公私钥都是拿工具直接生成的。
    工具地址:https://www.bejson.com/enc/rsa/

    在这里插入图片描述

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

    在这里插入图片描述

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

    下载forge

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

    在这里插入图片描述

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

    4)编写前置脚本

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

    所以最简单的方式:
    拿到js文件;
    运行;
    将参数进行加密;

     // ------ 导入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"));
    
    • 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

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

    这种方式接口的测试结果

    在这里插入图片描述

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

    在这里插入图片描述

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

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

    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
    • 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

    优点:

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

    测试结果:

    在这里插入图片描述

    下面是我整理的2023年最全的软件测试工程师学习知识架构体系图

    一、Python编程入门到精通

    请添加图片描述

    二、接口自动化项目实战

    请添加图片描述

    三、Web自动化项目实战

    请添加图片描述

    四、App自动化项目实战

    请添加图片描述

    五、一线大厂简历

    请添加图片描述

    六、测试开发DevOps体系

    请添加图片描述

    七、常用自动化测试工具

    请添加图片描述

    八、JMeter性能测试

    请添加图片描述

    九、总结(尾部小惊喜)

    每一次努力都是为了改变命运,每一次奋斗都是为了实现梦想。不要停下脚步,勇敢追逐,你的努力将成就辉煌,让世界为之震动。

    人生犹如航行大海,不要畏惧风浪,勇往直前。只有敢于冒险,坚持不懈地奋斗,才能驶向属于自己的成功港湾,让梦想在风帆下翱翔。

    永不止步,不论前路如何艰险,坚持追求梦想的勇气和决心。相信自己的能力,勇敢面对挑战,只有奋斗才能让我们在人生舞台上闪耀不灭的光芒。

  • 相关阅读:
    SCS RC翠鸟回收成分认证是什么?如何申请?需要什么
    找准边界,吃定安全 | 流量剧增?看山石网科如何打破传统限制
    Proxy代理配置解析
    Java高级学习栈(史上最详细的整合)
    E. Nastya and Potions
    计算机网络八股文
    Java异常及处理方式
    vuex常用属性
    什么是SHA384,SHA384和SHA512有什么区别
    java计算机毕业设计人才库构建研究源程序+mysql+系统+lw文档+远程调试
  • 原文地址:https://blog.csdn.net/csdnchengxi/article/details/134245233