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

news2024/11/26 10:47:58

目录:导读

    • 前言
    • 一、Python编程入门到精通
    • 二、接口自动化项目实战
    • 三、Web自动化项目实战
    • 四、App自动化项目实战
    • 五、一线大厂简历
    • 六、测试开发DevOps体系
    • 七、常用自动化测试工具
    • 八、JMeter性能测试
    • 九、总结(尾部小惊喜)


前言

一些问题

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}}"
 }

补充:用双层大括号包裹的参数,是引用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

在这里插入图片描述

这样就算安装完了,否则会一直报没有找到 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"));

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

这种方式接口的测试结果

在这里插入图片描述

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

在这里插入图片描述

如果同一个请求中有多个参数要进行加密,那岂不是要写多次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));
         }
     }
 });

优点:

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

测试结果:

在这里插入图片描述

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

一、Python编程入门到精通

请添加图片描述

二、接口自动化项目实战

请添加图片描述

三、Web自动化项目实战

请添加图片描述

四、App自动化项目实战

请添加图片描述

五、一线大厂简历

请添加图片描述

六、测试开发DevOps体系

请添加图片描述

七、常用自动化测试工具

请添加图片描述

八、JMeter性能测试

请添加图片描述

九、总结(尾部小惊喜)

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1179107.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

「Verilog学习笔记」位拆分与运算

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点,刷题网站用的是牛客网 1、寄存器的位是可以分开单独运算的,并不是一个输入就一定是一个数据,在很多情况下,一个输入既包括数据又包括地址等其他有效信息 2、需…

Android 分享图片和文案

一、业务描述 大多数App的需求中,有分享功能,点击唤起系统的分享栏,然后分享内容,例如指定文案,链接,图片等等。 二、实现逻辑 1.拿到要分享图片和内容 2.图片拿到缓存里,用于分享 3.使用F…

Tomcat 9.0.x 源码编译

文章目录 一、克隆源码二、构建 Maven1)在项目根目录中新建 pom.xml 文件2)然后 Add Maven Projects 三、在目录中增加 home 目录四、增加启动配置五、其它问题1)控制台乱码解决 2)启动后访问 localhost:8080 报错解决 一、克隆源…

SpringBoot + 微信支付 --- 内网穿透ngrok(安装、使用) 及 支付通知-->接收支付通知和返回应答

目录 Native 下单1、内网穿透 ngrok1-1:注册下载2-2:使用方式3-3:测试 2、支付通知--接收支付通知和返回应答完整需求介绍:2-1、需求1:应答测试2-2、应答的代码:2-3、结果:测试:应答…

vscode配置环境变量

首先点击下面这个链接。 sMinGW-w64 - for 32 and 64 bit Windows - Browse Files at SourceForge.net 然后选择Files这个选项 向下移选择下载这个文件 解压完成之后,找到这个文件的bin目录复制路径后,添加到环境变量中 依次点击后打开cmd&#xff0…

高性能三防工业平板电脑 防摔防爆电容屏工控平板

HT1000是一款高性能工业三防平板,10.1英寸超清大屏,厚度仅14.9mm,超薄机身,可轻松插入袋中,方便携带,搭载8核2.0GHz高性能CPU,行业领先的Android 11.0,设备性能大幅提升,…

通过使用Amazon Neptune来预测电影类型初体验

文章目录 福利来袭Amazon Neptune什么是图数据库为什么要使用图数据库什么是Amazon NeptuneNeptune 的特点 快速入门环境搭建notebook 图神经网络快速构建加载数据配置端点Gremlin 查询清理 删除环境S3 存储桶删除 福利来袭 前几天有小伙伴在群里灵魂发问:双11到来…

245:vue+openlayers 利用canvas绘制边线纹路

第245个 点击查看专栏目录 本示例的目的是介绍如何在vue+openlayers项目中利用canvas绘制边线纹路。思路就是将stroke渲染通过canvas设定的pattern模式。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共170行)专…

大语言模型研究进展综述

1、历史 自20世纪50年代图灵测试被提出以来,研究人员一直在探索和开发能够理解并掌握语言的人工智能技术。 作为重要的研究方向之一,语言模型得到了学术界的广泛研究,从早期的统计语言模型和神经语言模型开始,发展到基于Transform…

EasyHttp框架的使用

项目的集成 // JitPack 远程仓库:https://jitpack.io maven { url https://jitpack.io } // 网络请求框架:https://github.com/getActivity/EasyHttp implementation com.github.getActivity:EasyHttp:12.5 // OkHttp 框架:https://github.c…

ssm+vue的疫情高校师生外出请假管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频: ssmvue的疫情高校师生外出请假管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller)三…

2023版Pycharm关闭一直显示closing project,正在关闭项目

点击 帮助 下的 查找操作 英文版为 Help 下的 Find Action 输入 Registry 禁用 ide.await.scope.completion 即可 PS:按 Ctrl F 输入可以快速检索

快速实现一个企业级域名 SSL 证书有效期监控巡检系统

Why 现在对于企业来说,HTTPS 已经不是可选项,已经成为一个必选项。HTTPS 协议采用 SSL 协议,采用公开密钥的技术,提供了一套 TCP/IP 传输层数据加密的机制。SSL 证书是一种遵守 SSL 协议的服务器数字证书,一般是由权威…

《golang设计模式》第三部分·行为型模式-04-迭代器模式(Iterator)

文章目录 1. 概念1.1 角色1.2 类图 2. 代码示例2.1 需求2.2 代码2.3 类图 1. 概念 迭代器(Iterator)能够在不暴露聚合体内部表示的情况下,向客户端提供遍历聚合元素的方法。 1.1 角色 InterfaceAggregate(抽象聚合)…

图像切分:将一张长图片切分为指定长宽的多张图片

1.需求 比如有一张很长的图片其大小为宽度779,高度为122552,那我想把图片切分为779乘以1280的格式。 步骤如下: 使用图像处理库(如PIL或OpenCV)加载原始图片。确定子图片的宽度和高度。计算原始图片的宽度和高度&am…

6、Python控制流:if语句、for循环、while循环、循环控制语句

文章目录 Python控制流:if语句、for循环、while循环、循环控制语句if语句示例:for循环示例:while循环示例:循环控制语句示例:最佳实践Python控制流:if语句、for循环、while循环、循环控制语句 控制流是编程中的基础概念,它允许我们根据不同的条件执行不同的代码块,或者…

day3作业

自己封装一个矩形类(Rect)&#xff0c;拥有私有属性:宽度(width)、高度(height)&#xff0c; 定义公有成员函数: 初始化函数:void init(int w, int h) 更改宽度的函数:set_w(int w) 更改高度的函数:set_h(int h) 输出该矩形的周长和面积函数:void show() #include <io…

哈尔滨招聘网站哪个好

哈尔滨招聘网站 吉鹿力招聘网 比较好&#xff0c;我们都知道在现代社会中&#xff0c;互联网已经成为了人们获取信息的主要渠道之一。在寻找工作方面也不例外。吉鹿力招聘网是哈尔滨找工作的求职招聘网站。 登录 吉鹿力招聘网 “注册账号”&#xff0c;然后输入个人基本信息&a…

Android-JobService

JobService 这里写目录标题 JobService一、API详解1 onStartJob2 onStopJob 二、onStartJob | onStopJob 返回值case 1case 2case 3 ref: 深入理解JobScheduler与JobService的使用 - 掘金 (juejin.cn) (28条消息) JobService的使用介绍_TechMerger的博客-CSDN博客 (28条消息) J…

使用 Threejs 从基础开始构建 3D 地球

需求 threejs学习-3D 地球 实现&#xff1a; 1、使用粒子效果模拟宇宙星空 2、贴图、模型等资源的加载 3、加载资源的监听 4、效果合成器 EffectComposer 的初级使用 5、在地球上设置坐标以及坐标涟漪动画 6、标点间建立飞线 7、简单动画建议先浏览一遍git地址上代码&#xff…