学习和使用 Postman 过程中遇到的问题和解决办法。
请求体类型
- form-data:键值对或文件
- x-www-from-urlencoded:键值对参数
- raw:JSON,Text,XML,HTML,JavaScript
- binary:把文件以二进制的方式传参
代码变量
将 JS 代码块设为全局变量,再使用 eval 方法执行并在前置脚本中设为变量进行使用,最后使用 {{变量名}} 进行引用


全局变量 VALUE 中设置变量:
var moment = require('moment');
// 当前时间
var timesNow = moment().format("YYYY-MM-DD HH:mm:ss");
var timesF1 = moment().format("YYYYMMDDHHmmss");
var timesF2 = moment().format("YYYYMMDDHHmmssSSS");
var timesF3 = moment().format("MMDDHHmmss");
var timesF4 = moment().format("YYYY-MM-DDThh:mm:ss.SSS");
//13 位时间戳
var times13 = Math.round(new Date().getTime());
请求 Pre-request Script 中引用:
// 获取当前时间,并设置为环境变量
eval(globals.mutl_time);
pm.environment.set("timeNow",timesNow);
pm.environment.set("times",times13);
当同一个 Collection 下的多个 request 引用的变量值如 requestid 需要相同时,不应使用环境变量或全局变量,应该在 Collection 或 request 的前置脚本中配置变量供后续 request 引用
设置请求头
// 生成 10 位时间戳
var times10 = (Date.now() / 1000)|0;
var secret = "12345"
// SHA256 加密
var sign = CryptoJS.SHA256(times10 + secret).toString().toUpperCase();
pm.request.headers.add({
key: 'Authorization',
value: 'AUTH signature="' + sign + '",timestamp="' + times10 + '"'
});
提取请求体
// 获取实际的请求体内容(动态变量如 $guid 会被解析成实际请求的值)
const resolvedRequestBody = pm.variables.replaceIn(pm.request.body.raw);
// 打印实际的请求体内容
console.log("Resolved Request Body:", resolvedRequestBody);
响应结果提取
JSON 提取器
var result = JSON.parse(responseBody);
pm.environment.set("token", result.token);
pm.environment.set("id", result.data.id);
正则表达式提取器
var result = responseBody.match(new RegExp('"token":"(.*?)"'))
pm.globals.set("token", result[1]);
内置动态参数
| 动态参数 | 说明 |
|---|---|
| {{$timestamp}} | 10 位当前时间戳 |
| {{$randomint}} | 0-1000 之间的随机整数 |
| {{$guid}} | guid 字符串 |
响应结果断言
常规断言
// 检查状态码是否为 200
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// 检查响应体中是否包含 "success"
pm.test("Body contains 'success'", function () {
pm.expect(pm.response.text()).to.include("success");
});
// 检查 JSON 响应中的 "status" 字段是否为 "ok"
pm.test("Status is ok", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.status).to.eql("ok");
});
// 检查响应时间是否小于 200ms
pm.test("Response time is less than 200ms", function () {
pm.expect(pm.response.responseTime).to.be.below(200);
});
// 检查 Content-Type 是否为 application/json
pm.test("Content-Type is application/json", function () {
pm.expect(pm.response.headers.get("Content-Type")).to.include("application/json");
});
// 检查返回的数组长度是否为 3
pm.test("Array length is 3", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.items.length).to.eql(3);
});
// 检查响应体中的字段
pm.test("Check response data", function () {
var jsonData = pm.response.json();
pm.expect(jsonData).to.have.property("name").that.is.a("string");
pm.expect(jsonData).to.have.property("age").that.is.a("number").above(18);
});
// 使用环境变量进行断言
pm.test("Check environment variable", function () {
pm.expect(pm.response.json().value).to.eql(pm.environment.get("expected_value"));
});
// 检查响应体是否为空
pm.test("Response body is not empty", function () {
pm.expect(pm.response.text()).to.not.be.empty;
});
// 检查响应体是否为 JSON
pm.test("Response is JSON", function () {
pm.response.to.be.json;
});
// 检查嵌套字段
pm.test("Check nested field", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.user.address.city).to.eql("New York");
});
// 使用正则表达式检查响应体
pm.test("Check regex match", function () {
pm.expect(pm.response.text()).to.match(/success/);
});
// 检查响应体中是否包含关键字 "error",如果包含则测试失败
pm.test("Check if response contains 'error' keyword", function () {
const responseBody = pm.response.text();
if (responseBody.includes("error")) {
throw new Error("Keyword 'error' found in response body");
}
});
MD5 加密
将参数数组根据 key 做正向排序,然后用 key1 = value1&key2 = value2……的形式拼接起来,最后将 &sercet = 秘钥字符串拼接在待签名字符串之后,并计算所得到的字符串的 MD5 值全部转为大写,即为 sign 的值
// 提取 body 并去掉注释行
var requestBody = pm.request.body.raw.replace(/\/\/.*$/gm, '');
// 获取实际的请求体内容(动态变量已被替换)并去掉注释行
const resolvedRequestBody = pm.variables.replaceIn(requestBody).replace(/\/\/.*$/gm, '');
// 把请求参数转成 JSON
var json_requestBody = JSON.parse(resolvedRequestBody);
// 使用 delete 去掉 sign
delete json_requestBody.sign;
// 对对象按照键名倒序排序
function reverseObjObjectKeys(obj) {
const reverseObj = {};
Object.keys(obj).reverse().forEach(key => {
reverseObj[key] = obj[key];
});
return reverseObj;
}
// 遍历 json_requestBody,将数组类型的参数转换为 JSON 字符串
function processRequestBody(body) {
const result = {};
for (const key in body) {
if (Array.isArray(body[key])) {
// 如果是数组,倒序排序并处理每个对象的字段顺序
const reversedArray = body[key].slice().sort(); // 倒序排序
const processedArray = reversedArray.map(item => {
// 对每个对象的字段按照字母顺序排序
return reverseObjObjectKeys(item);
});
result[key] = JSON.stringify(processedArray);
} else if (typeof body[key] === 'object' && body[key] !== null) {
// 如果是嵌套对象,递归处理
result[key] = processRequestBody(body[key]);
} else {
// 其他类型直接赋值
result[key] = body[key];
}
}
return result;
}
const processedBody = processRequestBody(json_requestBody);
// 对参数按照键名正向排序
const sortedKeys = Object.keys(processedBody).sort();
// 拼接成 key1 = value1&key2 = value2… 格式的字符串
const concatenatedString = sortedKeys.map(key => `${key}=${processedBody[key]}`).join('&');
console.log("sign加密字符串:", concatenatedString);
// 对拼接后的字符串进行 MD5 加密
const CryptoJS = require('crypto-js');
const encryptedString = CryptoJS.MD5(concatenatedString).toString().toUpperCase();
json_requestBody.sign = encryptedString;
// 将更新后的请求体重新设置为请求体
pm.request.body.raw = JSON.stringify(json_requestBody);
AES 加密
// 提取 body 并去掉注释行
var requestBody = pm.request.body.raw.replace(/\/\/.*$/gm, '');
// 获取实际的请求体内容(动态变量已被替换)并去掉注释行
const resolvedRequestBody = pm.variables.replaceIn(requestBody).replace(/\/\/.*$/gm, '');
// 把请求参数转成 JSON
var json_requestBody = JSON.parse(resolvedRequestBody);
// 打印提取的实际请求体内容
console.log("原始请求体:", json_requestBody);
// 使用 delete 去掉 sign
delete json_requestBody.sign;
// 不参与 AES 加密请求体的参数
var timestamp = json_requestBody.timestamp;
var requestId = json_requestBody.requestId;
// 使用 delete 去掉不参与 AES 加密的参数
delete json_requestBody.timestamp;
delete json_requestBody.requestId;
// 加密函数:AES ECB 256 PKCS7
function aesEncrypt(data, key) {
const CryptoJS = require('crypto-js');
// 将密钥转换为 CryptoJS 格式
const cryptoKey = CryptoJS.enc.Utf8.parse(key);
// 加密配置:ECB 模式,PKCS7 填充
const encrypted = CryptoJS.AES.encrypt(data, cryptoKey, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
// 返回加密后的结果(Base64 格式)
return encrypted.toString();
}
// 请求体转换为字符串
const bodyString = JSON.stringify(json_requestBody);
console.log("AES加密前:", bodyString);
const encryptedData = aesEncrypt(bodyString, resolvedAppKey);
// 构建新的请求体,包含 xdata 和 timestamp
const newRequestBody = {
timestamp: timestamp, // 保留原始 timestamp
requestId: requestId,
xdata: encryptedData // 添加 AES 加密后的数据
};
// 对参数按照键名正向排序
const sortedKeys = Object.keys(newRequestBody).sort();
// 拼接成 key1 = value1&key2 = value2… 格式的字符串
const concatenatedString = sortedKeys.map(key => `${key}=${newRequestBody[key]}`).join('&');
console.log("sign加密字符串:", concatenatedString);
// 对拼接后的字符串进行 MD5 加密
const CryptoJS = require('crypto-js');
const md5sign = CryptoJS.MD5(concatenatedString).toString().toUpperCase();
// 请求体中添加签名
newRequestBody.sign = md5sign;
// 以新的请求体发起请求
pm.request.body.raw = JSON.stringify(newRequestBody);
- 本文作者:Nine
- 本文链接:https://blog.nine.gt.tc/2022/08/05/postman-skill/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)