系列文章目录
文章目录
前言
一、需求背景
通过Apifox管理api接口后,基于参数签名接口如何使用Apifox进行签名。
二、行动方案
1. 接口根目录—维护前置操作公共脚本(可默认启用)
前置脚本(自动加签)内容:
//动态拦截请求基于参数密钥自动加签
let requesUrl = pm.request.url;
let requesHeaders = pm.request.headers;
console.info('requesUrl:' + requesUrl);
console.info('requesHeaders:' + requesHeaders);
let requestUrlQuery = pm.request.url.query;
let requestBody = pm.request.body;
let requestBodyRaw = pm.request.body.raw;
let requestBodyFormData = pm.request.body.formdata;
let requestBodyUrlencode = pm.request.body.urlencode;
//console.info('requestUrlQuery:' + requestUrlQuery);
//console.info('requestBody:' + requestBody);
//console.info('requestBodyRaw:' + requestBodyRaw);
//console.info('requestBodyFormData:' + requestBodyFormData);
//console.info('requestBodyUrlencode:' + requestBodyUrlencode);
let tenantId = requesHeaders.get("tenantId");
let appId = requesHeaders.get("appId");
let appKey = requesHeaders.get("appKey");
if(tenantId != undefined) {
console.warn('tenantId为空');
//return;
}
if(!appId) {
console.error('appId为空');
return;
}
if(!appKey) {
console.error('appKey为空');
return;
}
// 存放所有需要用来签名的参数
let signParam = {};
//加入requesUrlQuery参数
let queryParams = requestUrlQuery;
if (queryParams) {
queryParams.each(item => {
if (!item.disabled && item.value !== '') { // 启用且非空参数值的参数才参与签名
signParam[item.key] = item.value;
}
});
}
//加入requestBody参数
if (requestBody) {
let formData
switch (pm.request.body.mode) {
case 'formdata':
formData = pm.request.body.formdata
break
case 'urlencoded':
formData = pm.request.body.urlencoded
break
case 'raw':
// 如果没有 JSON 格式的请求 body,或 JSON 格式 body 不参与签名,可以删除这一段
let contentType = pm.request.headers.get('content-type')
if (
contentType &&
pm.request.body.raw &&
contentType.toLowerCase().indexOf('application/json') !== -1
) {
try {
let jsonData = JSON.parse(pm.request.body.raw)
/*
* 注意:通过脚本取出来的接口参数,如果参数包含变量,变量是不会替换成对应的值。如想要获取替换后的值,可使用`pm.variables.replaceIn`方法处理:
* let body = pm.variables.replaceIn(pm.request.body.raw);
* let jsonData = JSON.parse(body);
*/
for (let key in jsonData) {
let value = `${jsonData[key]}` // 此处要注意如果值的实际类型不是 string 需要根据实际情况处理。
if (value !== '') {
// 非空参数值的参数才参与签名
signParam[key] = value
}
}
} catch (e) {
console.log('请求 body 不是 JSON 格式')
}
}
break
default:
break
}
if (formData) {
formData.each((item) => {
if (!item.disabled && item.value !== '') {
// 启用且非空参数值的参数才参与签名
signParam[item.key] = item.value
}
})
}
}
//加签
// 获取10位时间戳
//var timestamp = Math.round(new Date().getTime()/1000).toString();
// 获取13位时间戳
let timestamp = new Date().getTime()
signParam['timestamp'] = timestamp;
signParam['appId'] = appId;
signParam['tenantId'] = tenantId;
let defaultValue = "null";
for (let key in signParam) {
if(signParam[key] == undefined) {
signParam[key] = defaultValue;
}
}
//取key
let keys = [];
for (let key in signParam) {
// 注意这里,要剔除掉 sign 参数本身
if (key !== 'sign') {
keys.push(key);
}
}
keys.sort();//参数名 ASCII 码从小到大排序(字典序)
// 转成键值对
let paramPair = [];
for (let i = 0, len = keys.length; i < len; i++) {
let k = keys[i];
//paramPair.push(k + '=' + encodeURIComponent(signParam[k])) // urlencode 编码
paramPair.push(k + '=' + signParam[k]) // urlencode 编码
}
paramPair.push("key=" + appKey);//最后加上appKey
let signStr = paramPair.join('&');//拼接链接符
let signature = CryptoJS.MD5(signStr).toString().toLowerCase();//加签
console.info('appId:' + appId + ',appKey:' + appKey);
console.info('签名内容:' + signStr);
console.info('签名:' + signature);
//pm.environment.set('signature', signature);
//pm.environment.set("timestamp", timestamp);
//pm.request.headers.add('timestamp', timestamp);
//pm.request.headers.add('signature', signature);
pm.request.headers.add({key: "timestamp",value: timestamp});
pm.request.headers.add({key: "signature",value: signature});
let requestTimestamp = new Date().getTime()
console.info(requestTimestamp + ' : timestamp:' + pm.request.headers.get('timestamp'));
console.info(requestTimestamp + ' : signature:' + pm.request.headers.get('signature'));