教你在Postman中对请求参数进行加密加签预处理!_postman rsa加密
目录
- 一、序言
- 二、Pre-request预请求脚本语法
- 三、Pre-request脚本实现请求参数加密加签
-
- 1、引入三方库
- 2、定义公私钥环境变量
- 3、预请求脚本实操
一、序言
开发和测试同学平时多少都会用Postman
进行后台接口调试,尤其是请求经过网关时,通常数据都需要进行加密传输,以及加签等操作。
这时候需要用到Pre-request
和Post-response
脚本,这篇文章将会详细介绍关于Postman这些脚本的小细节。
二、Pre-request预请求脚本语法
1、Pre-request脚本简介
通过名字就可以看出来,Pre-request脚本会在请求发送到服务端前执行,如下:
预请求脚本可以在Collections(集合)、Folder(文件夹)和API接口上定义,如果三者都定义了预请求脚本,那么执行顺序为:Collections > Folder > API接口
。
备注:Postman运行环境基于
Node.js
,因此相关JS语法可以无缝迁移。
2、Postman中的变量
Postman中支持各种作用域变量定义,支持的作用域有Global
(全局)、Collection
(集合)、Environment
(环境变量)、Data
和Local
(脚本中本地变量),变量访问优先级从内到外,依次递增,如下:
通过pm
内置对象可以访问各作用域的变量,如pm.gloabal
或pm.environment
等等,如下:
// collection var \'score\' = 1// environment var \'score\' = 2// first request runconsole.log(pm.variables.get(\'score\')); // outputs 2console.log(pm.collectionVariables.get(\'score\')); // outputs 1console.log(pm.environment.get(\'score\')); // outputs 2// second request runpm.variables.set(\'score\', 3);// local varconsole.log(pm.variables.get(\'score\')); // outputs 3// third request runconsole.log(pm.variables.get(\'score\')); // outputs 2
备注:通过
pm.variables
对象获取变量时会根据上图中的优先级从里到外获取。
除此之外,Postman中还内置了一些动态变量,这些动态变量可以通过{{$guid}}
花括号进行引用,如下:
在脚本中可以通过pm.variables.replaceIn()
方法进行引用,如下:
const stringWithVars = pm.variables.replaceIn(\"Hi, my name is {{$randomFirstName}}\");console.log(stringWithVars);
3、Postman中的全局对象
Postman中支持常用的Javascript全局对象,可以看到大部分都支持。
除此之代,Postman还内置了一些三方库,比如moment.js、uuid.js等,使用内置三方库格式如下:
const moment = pm.require(\'moment\');const now = moment().format(\'YYYY-MM-DD HH:mm:ss\');console.log(\"当前时间: \"+ now);
三、Pre-request脚本实现请求参数加密加签
目前前端常见的加解密库有CryptoJS
、jsencrypt
和jsrsasign
,关于如何通过这些库实现对称加解密、非对称加解密&加验签的细节可以参考我之前的两篇文章:
- 前端CryptoJS和Java后端数据互相加解密(AES)
- 前后端RSA互相加解密、加签验签、密钥对生成
接下来的例子将以RSA非对称加密和加签为例,通过postman预请求脚本进行操作。
1、引入三方库
这里我使用了jsencrypt
和jsrsasign
两个库,首先定义了两个全局变量,变量的值为对应库的js脚本,如下:
通过全局变量获取到脚本内容后,通过eval()
函数动态加载执行,就能获取到相关全局对象。
备注:这两个库的脚本可直接在
https://cdnjs.com/
上搜索获取。
2、定义公私钥环境变量
开发、测试环境使用的公私钥都不一样,最好用环境变量进行区分,这里我定义了两个环境变量来存储公钥和私钥,如下:
备注:前端第三方库要求publicKey和privateKey的格式为标准pem格式,需要带
-----BEGIN PUBLIC KEY-----
前缀。
3、预请求脚本实操
这里的预请求脚本可以作用在Collections、文件夹或者单个接口上,我一般全局定义在某个Collections上。
脚本内容如下:
/** * RSA加密 */function encryptByRSA(publicKey, plainText) { eval(pm.globals.get(\'jsencrypt\')); const encryptor = new window.JSEncrypt(); encryptor.setPublicKey(publicKey); return encryptor.encrypt(plainText);}/** * RSA SHA256加签 */function signBySHA256WithRSA(privateKey, msg) { eval(pm.globals.get(\'jsrsasign\')); const key = KEYUTIL.getKey(privateKey); const signature = new KJUR.crypto.Signature({ alg: \"SHA256withRSA\", }); signature.init(key); signature.updateString(msg); // 签名后的为16进制字符串,这里转换为16进制字符串 return hextob64(signature.sign());}function sign(data) { // 获取私钥 const privateKey = pm.environment.get(\'privateKey\'); const signatureStr = signBySHA256WithRSA(privateKey, data); console.log(`生成的签名为: ${signatureStr}`) return signatureStr;}function encrypt() { // 获取公钥 const publicKey = pm.environment.get(\'publicKey\'); // 获取请求体 const requestBody = pm.request.body.raw; if (!requestBody) { return; } console.log(\"请求数据:\" + requestBody); try { // 将请求体解析为JSON对象 const jsonData = JSON.parse(requestBody); // 要加密的字段名 (替换为实际需要加密的字段名) const encryptedFields = [\"password\", \"encryptPwd\", \"newEncryptPwd\", \"paymentPin\", \"loginPwd\"]; const filterFields = encryptedFields.filter(v => jsonData[v]); if (!filterFields) { return; } filterFields.forEach(field => { // 加密指定字段 const plainText = jsonData[field]; const encryptedValue = encryptByRSA(publicKey, plainText) console.log(`字段[${field}]加密后的内容为:${encryptedValue}`) // 更新JSON中的值 jsonData[field] = encryptedValue; // 将修改后的JSON转回字符串并更新请求体 pm.request.body.raw = JSON.stringify(jsonData); }) return jsonData; } catch (error) { console.error(\"加密过程发生错误:\", error); }}// 定义全局变量const navigator = {};const window = {};const jsonData = encrypt();
这里需要注意的是,脚本最后为什么要定义navigator
和window
两个全局变量,原因如下:
- JSEncrypt依赖于window和navigator对象,没有这两对象访问会失败。
- 前面说过Postman基于Node.js运行,而window和navigator是浏览器特有的对象。
备注:关于pm.request和pm.response等对象的数据结构可参考Postman变量结构说明。