postman之接口参数签名(js接口HMAC-SHA256签名)

文章目录

  • postman之接口参数签名(js接口签名)
    • 一、需求背景
    • 二、签名生成规则
    • [三、postman js接口签名步骤](#三、postman js接口签名步骤)
      • [1. postman设置全局、或环境参数](#1. postman设置全局、或环境参数)
      • [2. 配置Pre-request Scripts脚本](#2. 配置Pre-request Scripts脚本)
    • [四、Pre-request Scripts脚本 常见工作整理](#四、Pre-request Scripts脚本 常见工作整理)
      • [1. js获取unix时间戳](#1. js获取unix时间戳)
      • [2. body json字符串进行md5运算](#2. body json字符串进行md5运算)
      • [3. JS字符串拼接](#3. JS字符串拼接)
      • [4. 哈希签名 HMAC-SHA256](#4. 哈希签名 HMAC-SHA256)
      • [5. PostMan 在请求中自动添加Header](#5. PostMan 在请求中自动添加Header)
      • [6. 使用PM对象访问与操作请求参数(pm.request.*)](#6. 使用PM对象访问与操作请求参数(pm.request.*))
      • [7. JS字符串拼接/连接](#7. JS字符串拼接/连接)
      • [8. JavaScript判断变量是否为空](#8. JavaScript判断变量是否为空)
    • 参考

postman之接口参数签名(js接口签名)

一、需求背景

在对外发布的接口中,基本上都会涉及到对接口字段进行签名加密,以防篡改。

后端接口为了避免参数被篡改,有参数签名的校验,为方便使用postman测试接口,可在postman设置自动签名。

Postman每发起一个请求之前,都可以选择执行一段pre-request script。这恰恰给了我们机会在请求发起之前生成我们需要的数据。

二、签名生成规则

不同项目签名规则不同。不过核心思路就是把你的请求需要防止篡改的部分进行HMAC-SHA256签名。

例如如下的待签名数据,使用 | 分隔 拼接你将来要签名的数据

bash 复制代码
method|url|timestamp|appKey|MD5(body)

三、postman js接口签名步骤

1. postman设置全局、或环境参数

postman 配置全局参数,设置 appKey、appSecret等全局参数

2. 配置Pre-request Scripts脚本

postman关键pre-script官方文档:https://learning.postman.com/docs/writing-scripts/script-references/postman-sandbox-api-reference/#scripting-with-request-info

配置脚本,编辑collection,选择Pre-request Scripts,输入脚本

完成以下能力

  • 获取签名参数
  • 生成签名
  • 赋值到指定heaher中

demo1:

javascript 复制代码
var appKey = pm.environment.get("appKey");
var appSecret = pm.environment.get("appSecret");
var queryParam = pm.request.url.query.members;
var timestamp = new Date().getTime();
 
let param = JSON.parse("{}");
 
for (let i in queryParam){
    param[queryParam[i].key] = queryParam[i].value;
}
param['timestamp'] = timestamp;
var keys = [];
for (let k in param){
    if (k == 'sign'){
        continue;
    }
    keys.push(k);
}
//排序
keys.sort();
 
//取value
var sign = '';
sign = sign + appSecret;
for (let k of keys){
    sign = sign+ (k + '' + encodeURIComponent(param[k]));
}
sign = sign+appSecret;
console.log(sign);
sign = CryptoJS.MD5(sign).toString();
console.log(sign);
pm.environment.set('sign',sign);
pm.environment.set('timestamp',timestamp);
pm.environment.set('appKey',encodeURIComponent(appKey));
javascript 复制代码
//获取url的path部分
getUrlRelativePath:function(url){
    var arrUrl = url.split("//");
    var start = arrUrl[1].indexOf("/");
    var end=arrUrl[1].indexOf("?");
    var relUrl = arrUrl[1].substring(start,end);//stop省略,截取从start开始到结尾的所有字符
    console.log(relUrl);
    return relUrl;
}

demo2:

javascript 复制代码
var appKey = pm.environment.get("appKey");
var appSecret = pm.environment.get("appSecret");


var method = pm.request.method
console.log('method:', method)

var url = pm.request.url.getPath()
console.log('url:', url)

var queryParam = pm.request.url.query.members;
console.log('queryParam:', queryParam)

// js获取unix时间戳 getTime()返回数值的单位是毫秒
var timestamp = new Date().getTime();
console.log('timestamp:', timestamp)


var body = pm.request.body.raw;
console.log('body:', body)

var bodyMd5= CryptoJS.MD5(body).toString();
console.log('bodyMd5:', bodyMd5)


// // 序列化
// var json="";
// try {
//   json = JSON.parse(body); //序列化JSON BODY
//   param = json;
// }catch(err){
//   //BODY不是JSON格式
//   console.log("json data error");
// }
// console.log(json);

// var jsonStringify = JSON.stringify(param).toString();
// console.log('jsonStringify:',jsonStringify);

// var bodyStrMd5= CryptoJS.MD5(jsonStringify).toString();
// console.log('bodyStrMd5:', bodyStrMd5)

tonce = new Date().getTime() * 1000
console.log('tonce:', tonce)

//method|url|tonce|accesskey|other|MD5(body)
var signatureRawData = `${method}|${url}|${tonce}|${appKey}|${bodyMd5}`
console.log('signatureRawData:', signatureRawData)



//生成哈希签名
var signature = CryptoJS.enc.Utf8.parse(signatureRawData);
//var secret_bytes = CryptoJS.enc.Base64.parse(appSecret);
var secret_bytes = CryptoJS.enc.Utf8.parse(appSecret);

var signatureBytes = CryptoJS.HmacSHA256(signature,secret_bytes)
console.log('signatureBytes:', signatureBytes)
var signStr = signatureBytes.toString()
console.log('signStr:', signStr)

var signatureRawData = `${method}|${url}|${tonce}|${appKey}|${bodyMd5}`

//认证头编码创建
var authorizationStr = `${appKey}:${signStr}`
console.log('authorizationStr:', authorizationStr)


var requestSignatureBase64String = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(authorizationStr));
console.log('requestSignatureBase64String:', requestSignatureBase64String)

//设置到postman环境变量中,postman  hearder引入该变量
pm.environment.set("signature",requestSignatureBase64String)

pm.request.headers.add({
    key: 'Authorization',
    value: requestSignatureBase64String
});

pm.request.headers.add({
    key: 'tonce',
    value: tonce
});

四、Pre-request Scripts脚本 常见工作整理

1. js获取unix时间戳

如何在 JavaScript 中获取 UNIX 时间戳

参考URL: https://blog.csdn.net/allway2/article/details/122558429

UNIX 时间戳是一个整数值,表示自UNIX 纪元于 1970 年 1 月 1 日 00:00:00 UTC以来经过的秒数。简而言之,这是一种将时间跟踪为运行总秒数的方法。因此,UNIX 时间戳只是特定日期和 UNIX 纪元之间的秒数。

JavaScriptDate对象提供了几种处理日期和时间的方法。now()您可以通过调用对象上的函数来获取当前时间戳,Date如下所示:

javascript 复制代码
const timestamp = new Date().getTime()

此方法以毫秒为单位返回当前的 UTC 时间戳。

getTime()返回数值的单位是毫秒

微秒级时间戳,我们这里直接乘以1000,因为js找不到获取微秒级的方法,谁知道可以评论区留言。这里我们乘以1000凑成微秒级的位数。

2. body json字符串进行md5运算

CryptoJS是一个前端加密的JS库,它可以进行MD5,AES等进行加密

这边直接使用CryptoJS.MD5即可

javascript 复制代码
var body=pm.request.body.raw;

// 序列化
var json="";
try {
  json = JSON.parse(body); //序列化JSON BODY
  param = json;
}catch(err){
  //BODY不是JSON格式
  console.log("json data error");
}
console.log(json);

var jsonStr = JSON.stringify(param).toString();
sign = CryptoJS.MD5(jsonStr).toString();

这里是对body的json解析出来后,然后 JSON.stringify 处理后,进行md5.

当然你也可以直接对body的原始内容,进行md5

javascript 复制代码
var body=pm.request.body.raw;
sign = CryptoJS.MD5(body).toString();

3. JS字符串拼接

JS字符串拼接的几种方式

参考URL: https://huaweicloud.csdn.net/63a568aeb878a54545946b76.html

在 JavaScript 中,使用字符串连接有 几 种方式:连接符(+)、反引号(`)、join()、concat()。

  • 使用模板字符串,以反引号( ` )标识

ES6中新增的字符串方法,可以配合反单引号完成拼接字符串的功能

反单引号怎么打出来:将输入法调整为英文输入法,单击键盘上数字键1左边的按键。

用法:

1: 定义需要拼接进去的字符串变量

2: 将字符串变量用${}包起来,再写到需要拼接的地方

javascript 复制代码
let a = 'java'
let b = `hello ${a}script`

接口签名demo:

对如下数据进行拼接,将来进行签名。

bash 复制代码
method|url|timestamp|appKey|MD5(body)
javascript 复制代码
var sign = `${method}|${url}|${timestamp}|${appKey}|${bodyMd5}`

4. 哈希签名 HMAC-SHA256

HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code)的缩写,由H.Krawezyk,M.Bellare,R.Canetti于1996年提出的一种基于Hash函数和密钥进行消息认证的方法, 并于1997年作为RFC2104被公布,并在IPSec和其他网络协议(如SSL)中得以广泛应用,现在已经成为事实上的Internet安全标准。它可以与任何迭代散列函数捆绑使用。

HMAC算法利用哈希运算,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。

使用SHA-1、SHA-224、SHA-256、SHA-384、SHA-512所构造的HMAC,分别称为HMAC-SHA1、HMAC-SHA-224、HMAC-SHA-256、HMAC-SHA-384、HMAC-SHA-512。

postman的脚本库中CryptoJS是支持各种算法的加密,包括HMACSHA256。

CryptoJS 是一个使用 JavaScript 实现的加密算法库

它支持的算法包含:

  • Base64
  • MD5
  • SHA-1 和 SHA-256
  • AES
  • Rabbit
  • MARC4
  • HMAC、HMAC-MD5、HMAC-SHA1、HMAC-SHA256
  • PBKDF2

demo例子:

javascript 复制代码
var signature = CryptoJS.enc.Utf8.parse(signatureRawData);
//var secret_bytes = CryptoJS.enc.Base64.parse(appSecret);
var secret_bytes = CryptoJS.enc.Utf8.parse(appSecret);

var signatureBytes = CryptoJS.HmacSHA256(signature,secret_bytes)
console.log('signatureBytes:', signatureBytes)
var signStr = signatureBytes.toString()
console.log('signStr:', signStr)

var requestSignatureBase64String = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(signStr));
console.log('requestSignatureBase64String:', requestSignatureBase64String)

总结:

HmacSHA256加密,var hash = CryptoJS.HmacSHA256(str, secret);

base64编码,var hashInBase64 = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(hash));

使用CryptoJS的hmac

CryptoJS官方文档:https://cryptojs.gitbook.io/docs/#encoders

使用secretkey利用HMAC生成哈希签名。使用SHA256作为哈希算法

  • CryptoJS.enc.Utf8.parse 把字符串转成UTF8编码

您不能简单地将字节发送到JavaScript。您需要将其转换为文本表示形式,以使其具有可比性。python的hmac模块和CryptoJS都支持十六进制编码。

CryptoJS:

CryptoJS.HmacSHA256("test", "secret").toString(CryptoJS.enc.Hex)

python:

hmac.new("secret", "test", hashlib.sha256).hexdigest()

注意参数顺序的差异。

两者都产生

0329a06b62cd16b33eb6792be8c60b158d89a2ee3a876fce9a881ebb488c0914

5. PostMan 在请求中自动添加Header

你可以再postman 的console看到发送的请求的header中添加了你的这里添加的header内容。

javascript 复制代码
// 添加新 header
pm.request.headers.add({
    key: 'Accept-Encoding',
    value: 'gzip'
});

// 添加或修改已存在 header
pm.request.headers.upsert({
    key: 'Connection',
    value: 'close'
});

// 移除 header
pm.request.headers.remove('User-Agent')

网上demo,这种方式,我们之间就在header中添加了这个 header,不用再到具体的接口header中添加环境变量(如下图),也是很方便。


6. 使用PM对象访问与操作请求参数(pm.request.*)

Postman进阶篇(十一)-在脚本中使用pm对象访问接口请求(pm.request.*)

参考URL: https://betheme.net/qianduan/44100.html?action=onClick

pm.request 对象可以在脚本中对请求数据进行访问。

接口请求的URL

pm.request.url //接口URL

通过URL对象对接口URL进行访问和操作

javascript 复制代码
//返回url对象
var url = pm.request.url
console.log('url:', url)

//通过URL对象对接口URL进行访问和操作
//返回请求路径:
var path = pm.request.url.getPath()
console.log('path:', path)

var path_with_query = pm.request.url.getPathWithQuery()
console.log('path_with_query:', path_with_query)

//以字符串格式,返回查询参数
var query_string = pm.request.url.getQueryString()
console.log('query_string:', query_string)

//返回主机和端口,用":"分隔
var remote = pm.request.url.getRemote()
console.log('remote:', remote)

执行结果:

7. JS字符串拼接/连接

在 JavaScript 中,使用字符串连接有 3 种方式。

  1. 字符串连接运算符"+"
  2. 字符串的concat()方法
javascript 复制代码
var s1 = "abc";
var s2 = s1.concat("d" , "e" , "f");  //调用concat()连接字符串
console.log(s2);  //返回字符串"abcdef"
  1. 数组的join()方法
    join 的好处在于,你可以自定义组合数组元素的方式。你可以通过在其参数中传递分隔符来实现。
javascript 复制代码
arrayObject.join(separator);

8. JavaScript判断变量是否为空

JavaScript判断变量是否为空

参考URL: http://aihongxin.com/791.html

JavaScript五种原始类型(boolean、number、string、null、undefined)

分别为 undefined,null,false,"",0,

JavaScript本身没有判断一个变量是不是空值的函数,因为变量有可能是string,object,number,boolean等类型,类型不同,判断方法也不同。

写了一个函数,用以判断JS变量是否空值,如果是undefined、 null、''、 NaN、false、0、[]、{} 、空白字符串,都返回true,否则返回false。

javascript 复制代码
function isEmpty(v) {
    switch (typeof v) {
    case 'undefined':
        return true;
    case 'string':
        if (v.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true;
        break;
    case 'boolean':
        if (!v) return true;
        break;
    case 'number':
        if (0 === v || isNaN(v)) return true;
        break;
    case 'object':
        if (null === v || v.length === 0) return true;
        for (var i in v) {
            return false;
        }
        return true;
    }
    return false;
}

参考

postman自动化接口测试

参考URL: https://zhuanlan.zhihu.com/p/158732164

Postman调试技巧之接口签名

参考URL: https://juejin.cn/post/6844903636649115655

postman 配置参数自动签名

参考URL: https://blog.csdn.net/qq_28058443/article/details/120704523

JSAPI签权

参考URL: http://www.javashuo.com/article/p-ubvsvhgx-bc.html

postman系列之接口参数签名

参考URL: https://blog.csdn.net/henglin/article/details/119621767

相关推荐
CodeClimb5 小时前
【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
光头程序员7 小时前
grid 布局react组件可以循数据自定义渲染某个数据 ,或插入某些数据在某个索引下
javascript·react.js·ecmascript
fmdpenny8 小时前
Vue3初学之商品的增,删,改功能
开发语言·javascript·vue.js
小美的打工日记8 小时前
ES6+新特性,var、let 和 const 的区别
前端·javascript·es6
涔溪9 小时前
有哪些常见的 Vue 错误?
前端·javascript·vue.js
程序猿online9 小时前
前端jquery 实现文本框输入出现自动补全提示功能
前端·javascript·jquery
Turtle11 小时前
SPA路由的实现原理
前端·javascript
HsuYang11 小时前
Vite源码学习(九)——DEV流程中的核心类(下)
前端·javascript·架构
傻小胖11 小时前
React 中hooks之useInsertionEffect用法总结
前端·javascript·react.js
蓝冰凌13 小时前
【整理】js逆向工程
javascript·js逆向