前言
在做接口测试时,出于安全因素,请求参数需要做加密或者加上签名才能正常请求,例如:根据填写的请求参数进行hash计算进行签名。postman作为主流的接口调试工具也是支持请求预处理的,即在请求前使用JavaScript脚本对参数进行一些预处理然后再进行引用。
背景
一般接口都是用Java语言写的,所以其加密算法也是Java语言写的,加密过程中可能会涉及到引用了Java相关的类库,所以在postman中进行涉及加密接口的请求时,需要先将Java加密算法转换成JavaScript代码,在转换过程中就可能引用到JS的类库。那么怎么在Postman中引用JS类库呢?假设我们要在Postman中引用CryptoJS库。
将Java代码转换为js代码
有以下Java签名算法
packageorg.example;importorg.apache.commons.codec.digest.DigestUtils;importjava.io.UnsupportedEncodingException;importjava.util.*;importjava.util.Map.Entry;/**
Unit test for simple App. */publicclassAppTest{publicstaticStringveritySign(SortedMap<String,Object> parameters,String key){StringBuffer sbkey =newStringBuffer();Set es = parameters.entrySet();Iterator it = es.iterator();String md5a;while(it.hasNext()){Entry entry =(Entry) it.next();
md5a =(String) entry.getKey();Object v = entry.getValue();if(null!= v &&!"".equals(v)){
sbkey.append(md5a +"="+ v +"&");}}
sbkey = sbkey.append("key="+ key);String sbString = sbkey.toString();
md5a ="";String content = sbkey.toString();char[] chars = content.toCharArray();String charset ="utf-8";int sum =0;char[] var12 = chars;int i = chars.length;for(int var14 =0; var14 < i;++var14){char aChar = var12[var14];
sum +=Integer.valueOf(aChar);}int num = sum %3+3;for(i =0; i < num;++i){try{
content =DigestUtils.md5Hex(content.getBytes(charset)).toUpperCase();}catch(UnsupportedEncodingException var16){
var16.printStackTrace();}}
md5a = content;System.out.println(md5a);return md5a;}publicstaticvoidmain(String[] args){String channelId ="12345678";String pid ="beijing";Long time =System.currentTimeMillis();String brand="Apple";String modal="iPhone 15 pro";String key ="123dzW127725c47534bdeqf6726de68z";//请求参数信息SortedMap<String,Object> paramMap =newTreeMap<>();
paramMap.put("modelCode", brand +" "+ modal);
paramMap.put("channelId", channelId);
paramMap.put("pid", pid);
paramMap.put("time", time);veritySign(paramMap, key);}}
转换为JS代码:
// 引入 CryptoJS 模块functionveritySign(parameters, key){let sbkey ='';for(const[keyParam, value]of Object.entries(parameters)){if(value !==null&& value !==''){
sbkey += keyParam +'='+ value +'&';}}
sbkey +='key='+ key;let content = sbkey;let chars = content.split('');let sum =0;for(let i =0; i < chars.length; i++){let aChar = chars[i];
sum += aChar.charCodeAt(0);}let num = sum %3+3;for(let i =0; i < num; i++){try{
content = CryptoJS.MD5(content).toString().toUpperCase();}catch(error){
console.error(error);}}let md5a = content;
console.log(md5a);return md5a;}// 测试用例(functionmain(){const channelId ='12345678';const pid ='beijing';const time = Date.now();const brand ='Apple';const modal ='iPhone 15 pro';const key ='123dzW127725c47534bdeqf6726de68z';// 请求参数信息const paramMap ={modelCode: brand +' '+ modal,channelId: channelId,pid: pid,time: time
};const signature =veritySign(paramMap, key);
console.log('Signature:', signature);})();
请注意以下几点:
- CryptoJS: 我们假设您已经在项目中包含了 CryptoJS 库,并且可以通过 require 或者 script标签引入它。
- Date.now(): JavaScript 中获取当前时间戳的方法与 Java 中System.currentTimeMillis() 相当。
- SortedMap: 在 JavaScript 中,我们使用 Object.entries 和 for…of 循环来遍历对象的键值对。由于 JavaScript 的 Object.entries返回的数组默认就是按添加顺序排序的,因此不需要额外的排序。
- 编码问题: JavaScript中处理字符串编码通常不是问题,因为字符串是以 UTF-16 编码的,但如果您需要明确地处理编码问题,可以使用 TextEncoder类(在现代浏览器中可用)或者第三方库如 Buffer (Node.js 中可用)。
- 测试用例: 我将 Java 中的main 方法转换成了一个立即执行的函数表达式 (IIFE),用于测试 veritySign 函数。
您可以将这段代码放在一个 HTML 文件中并运行它,或者在 Node.js 环境中运行它,只要确保 CryptoJS 库已经被正确加载。
这里是修改后的代码,用于在 Postman 的预请求脚本中使用 CryptoJS:
在postman中进行引用
在 Postman 的预请求脚本中,您不能使用 window 对象(浏览器对象),因为预请求脚本是在 Node.js 环境中运行的,而不是在浏览器环境中运行的。因此,window 对象是不可用的。您应该直接使用 require 来加载 CryptoJS 模块。
步骤 1: 安装 CryptoJS
首先,确保您已经在本地机器上安装了 Node.js 和 npm。然后,安装 CryptoJS 模块:
npminstall crypto-js
步骤 2: 在 Postman 中引用 CryptoJS
接下来,在 Postman 的预请求脚本中引用 CryptoJS:
测试脚本需要做一点点改动,需要将签名字符串设置成postman全局变量在请求体中引用:
// 将生成的签名存储到全局变量中
pm.globals.set("sign", sign);
postman完整pre request代码
// 引入 CryptoJS 模块var CryptoJS =require('crypto-js');// 修改后的 veritySign 函数functionveritySign(parameters, key){let sbkey ='';for(const[key, value]of Object.entries(parameters)){if(value !==null&& value !==''){
sbkey += key +'='+ value +'&';}}
sbkey +='key='+ key;let sbString = sbkey;let content = sbkey;let chars = content.split('');let sum =0;for(let i =0; i < chars.length; i++){let aChar = chars[i];
sum += aChar.charCodeAt(0);}let num = sum %3+3;for(let i =0; i < num; i++){try{
content = CryptoJS.MD5(content).toString().toUpperCase();}catch(error){
console.error(error);}}let md5a = content;
console.log(md5a);return md5a;}// 初始化参数const channelId ='12345678';const pid ='beijing';const time = Date.now();const brand ='Apple';const modal ='iPhone 15 pro';const key ='123dzW127725c47534bdeqf6726de68z';let paramMap ={modelCode: brand +' '+ modal,channelId: channelId,pid: pid,time: time
};// 调用 veritySign 函数let sign =veritySign(paramMap, key);// 将生成的签名存储到全局变量中
pm.globals.set("sign", sign);
注意事项
- 确保 CryptoJS 已经安装:确保您已经在本地机器上安装了 CryptoJS 模块。
- 使用
require
导入模块:在 Postman 的预请求脚本中使用require
来导入 CryptoJS 模块。 - 异步问题:上述代码中的
veritySign
函数是同步的,这意味着它会在 Postman 的预请求脚本中立即执行。如果您需要处理异步操作,可以使用回调函数或 Promise 来实现。
按照上述步骤,您应该能够在 Postman 的预请求脚本中使用 CryptoJS 并生成所需的签名。
测试
打开postman控制台,点击待测接口并请求,查看控制台日志打印:
可以看到请求签名是OK的,这样我们就能在请求body中引用了:
版权归原作者 知识的宝藏 所有, 如有侵权,请联系我们删除。