接口签名和postman预处理生成签名

nestjs后端代码

controller

 @Get('md5hmacSHA1b64')
  postMd5hmacSHA1b64(@Req() request: Request, @Query() query) {
    // 获取GET请求参数
    const queryParamsMap = new Map(Object.entries(query));
    return this.handleMd5hmacSHA1b64(queryParamsMap, request);
  }

  @Post('md5hmacSHA1b64')
  @UseInterceptors(NoFilesInterceptor())
  getMd5hmacSHA1b64(@Req() request: Request, @Body() formData) {
    //@Body() formData 支持 x-www-form-urlencoded 和 application/json 类型的请求, 但是不支持普通表单 form-data
    //form-data支持文件上传, x-www-form-urlencoded不支持文件上传
    //使用 @UseInterceptors(NoFilesInterceptor()) 让@Body()支持form-data键值对形式的非文件上传场景
    console.log('formData:', formData);
    //提取formData的键值对
    const query2 = new Map(Object.entries(formData));
    console.log('query2:', query2);
    return this.handleMd5hmacSHA1b64(query2, request);
  }

  private handleMd5hmacSHA1b64(
    queryParamsMap: Map<string, any>,
    request: Request,
  ) {
    //获取header列表
    //const queryHeadersMap = new Map(Object.entries(request.headers));
    //queryHeadersMap 只取出指定header accessKeyId nonce timestamp
    const queryHeadersMap2 = new Map(
      Object.entries(request.headers).filter(
        (item) =>
          item[0] === 'accesskeyid' ||
          item[0] === 'nonce' ||
          item[0] === 'timestamp' ||
          item[0] === 'sign',
      ),
    );
    //queryHeadersMap2 的 key  accesskeyid 替换为 accessKeyId
    queryHeadersMap2.forEach((value, key) => {
      if (key === 'accesskeyid') {
        queryHeadersMap2.set('accessKeyId', value);
        queryHeadersMap2.delete('accesskeyid');
      }
    });
    //将上面两个map合并
    const allMap = new Map([...queryParamsMap, ...queryHeadersMap2]);
    return this.epgService.md5hmacSHA1b64(allMap);
  }

private handleMd5hmacSHA1b64(
    queryParamsMap: Map<string, any>,
    request: Request,
  ) {
    //获取header列表
    //const queryHeadersMap = new Map(Object.entries(request.headers));
    //queryHeadersMap 只取出指定header accessKeyId nonce timestamp
    const queryHeadersMap2 = new Map(
      Object.entries(request.headers).filter(
        (item) =>
          item[0] === 'accesskeyid' ||
          item[0] === 'nonce' ||
          item[0] === 'timestamp' ||
          item[0] === 'sign',
      ),
    );
    //queryHeadersMap2 的 key  accesskeyid 替换为 accessKeyId
    queryHeadersMap2.forEach((value, key) => {
      if (key === 'accesskeyid') {
        queryHeadersMap2.set('accessKeyId', value);
        queryHeadersMap2.delete('accesskeyid');
      }
    });
    //将上面两个map合并
    const allMap = new Map([...queryParamsMap, ...queryHeadersMap2]);
    return this.epgService.md5hmacSHA1b64(allMap);
  }

service代码

md5hmacSHA1b64(allMap: Map<string, any>) {
    const accessKeyId =process.env.ACCESS_KEY_ID;
    const accessKeySecret = process.env.ACCESS_KEY_SECRET;

    console.log(allMap);
    //遍历allMap列表,拷贝到headerMap
    const sign = allMap.get('sign');
    console.log("sign", sign)
    const headerMap = {};
    for (const key of allMap.keys()) {
      // 去掉名为sign的key
      if (key !== 'sign') {
        headerMap[key] = allMap.get(key);
      }
    }
    console.log('headerMap=', headerMap)
    //accessKeyId 替换为约定的accessKeyId
    headerMap['accessKeyId'] = accessKeyId;

    //对headerMap按字母排序
    const sortHeaderMap = {};
    Object.keys(headerMap)
        .sort()
        .forEach((key) => {
          sortHeaderMap[key] = headerMap[key];
        });
    console.log('sortHeaderMap=', sortHeaderMap);

    //对排序后的header拼接字符串 形如 key1=value1&key2=value2&key3=value3的形式,最后一项没有&
    let str = '';
    for (const key in sortHeaderMap) {
      str += key + '=' + sortHeaderMap[key] + '&';
    }
    str = str.substring(0, str.length - 1);

    //base64
    const base64 = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(str));
    //hmacsha1
    const hmacsha1 = CryptoJS.HmacSHA1(base64, accessKeySecret);
    //md5
    const md5 = CryptoJS.MD5(hmacsha1).toString();
    //判断sign==md5 若相等 返回check 字段为ok
    return {
      str,
      md5hmacSHA1b64: md5,
      check: sign === md5?'ok':'no',
    };
  }

postman接口

header定义

pre-Request预处理脚本

// 辅助函数:补零
function padZero(num) {
    return num.toString().padStart(2, '0');
}
// 生成16位随机数,用于nonce
function generateRandom16bit() {
    return Math.random().toString(16).substring(2, 18);
}
//验证请求GET POST ok
let accessKeyId = "UC1"; //签名Key
let accessKeySecret = "UC2"; //签名secret
//let accessKeyId = pm.request.headers.get("accessKeyId");

let param = {};
console.log("param:",param)


// 获取当前时间戳
const now = new Date();
// 时间戳 格式化为指定样式  yyyyMMddHHmmss
const formattedTimestamp = 
    now.getFullYear().toString() + // 年份
    padZero(now.getMonth() + 1) + // 月份,注意月份是从0开始的,所以加1
    padZero(now.getDate()) +
    padZero(now.getHours()) +
    padZero(now.getMinutes()) +
    padZero(now.getSeconds());

//16位随机数
let nonce = generateRandom16bit()

//头部参数
param['accessKeyId']=accessKeyId
param['nonce']=nonce
param['timestamp']=formattedTimestamp

//Get 参数
let queryParam = pm.request.url.query.members;
console.log("queryParam:",queryParam)
for (let i in queryParam){
    param[queryParam[i].key] = queryParam[i].value;
}
//POST参数
let postParam = request.data;
console.log("postParam:",postParam)
if(typeof(postParam) == "string"){
    try{
        let dataJson = JSON.parse(postParam);
        // 将解析后的数据合并到param对象中
        Object.assign(param, dataJson);
    }catch(err){
        console.log(err)
    }
}else{
    Object.assign(param, postParam);
}

console.log("allParam:",param)
//Post
//取key
var keys = [];
for (let k in param){
    if (k == 'sign'){
        continue;
    }
    keys.push(k); 
}
//排序
keys.sort();

//取value
var kv = [];
for (let k of keys){
    kv.push(k + '=' + param[k]) 
    
}

//拼接
var str = kv.join('&');

console.log("str=",str)
//签名计算算法md5(hmacsha1(base64(str)))
const base64 = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(str));
const hmacsha1 = CryptoJS.HmacSHA1(base64, accessKeySecret);
const md5 = CryptoJS.MD5(hmacsha1).toString();

//设置环境变量
postman.setEnvironmentVariable("nonce", nonce);
postman.setEnvironmentVariable("timestamp", formattedTimestamp);
postman.setEnvironmentVariable("sign", md5);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/676893.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

达梦数据库相关SQL及适配Mysql配置总结

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

ApiJson简单使用

前言 最近在正式迭代中插入了一个大屏演示项目&#xff0c;因为后端开发人员任务都安排满了&#xff0c;而演示项目逻辑比较简单&#xff0c;大多是直接查表就能搞定&#xff0c;所以只能想办法让前端直接和数据库交互&#xff0c;增加开发速度。在找工具时发现了ApiJson。尝试…

C语言学习之结构体

结构体&#xff1a; c语言---提供的一种方式&#xff0c;可以让用户自定义数据类型&#xff0c;用于处理复杂的数据类型。 struct 结构体名 { 成员表列 }; 构造一个结构体 结构体变量的引用: 方法: 结构体变量名.成员名 . 结构体成员运算符 //表示 从属关系 s.name //表…

MySQL-权限管理(二)

一 host中的含义 /usr/local/mysql/bin/mysql -pLXYlxy2:024.#8u} -S /data/mysql/tmp/mysqld.sock select user,host,authentication_string from mysql.user; %:主要允许从任何主机连接到MySQL服务器&#xff0c;即外部连接localhost: 代表只允许本地主机连接到MySQL服务器&…

SpringBoot——整合Servlet的三大组件:过滤器(Filter)

目录 过滤器 一、用过滤器检查用户是否登录 LoginFilter自定义过滤器 FilterConfig配置类 FilterController控制器 SpringbootFilterApplication启动类 二、用过滤器统计资源访问量 LoginFilter FilterController 在开发SpringBoot项目时&#xff0c;开发人员经常需…

使用Obfuscar 混淆WPF(Net6)程序

Obfuscar 是.Net 程序集的基本混淆器&#xff0c;它使用大量的重载将.Net程序集中的元数据&#xff08;方法&#xff0c;属性、事件、字段、类型和命名空间的名称&#xff09;重命名为最小集。详细使用方式参见&#xff1a;Obfuscar 在NetFramework框架进行的WPF程序的混淆比较…

乡村振兴的乡村旅游品质提升:提升乡村旅游服务质量,打造乡村旅游品牌,增强乡村旅游吸引力,打造具有旅游特色的美丽乡村

目录 一、引言 二、提升乡村旅游服务质量 1、完善基础设施建设 2、提升服务人员素质 3、规范服务流程 三、打造乡村旅游品牌 1、挖掘乡村文化特色 2、打造特色旅游产品 3、加强品牌宣传和推广 四、增强乡村旅游吸引力 1、创新旅游体验方式 2、打造旅游精品线路 3、…

【NOI】C++程序结构入门之循环结构二-for循环

文章目录 前言一、for循环1.导入2.语法3.使用场景4.条件控制5.小结 二、例题讲解问题&#xff1a;1264 - 4位反序数问题&#xff1a;1085 - 寻找雷劈数问题&#xff1a;1057 - 能被5整除且至少有一位数字是5的所有整数的个数问题&#xff1a;1392 - 回文偶数&#xff1f;问题&a…

Windows下设置pip代理(proxy)

使用场景 正常网络情况下我们安装如果比较多的python包时&#xff0c;会选择使用这种 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-hostpypi.tuna.tsinghua.edu.cn 国内的镜像来加快下载速度。 但是&#xff0c;当这台被限制上…

Python 图书馆管理系统(MySQL数据库) 有GUI界面 【含Python源码 MX_032期】

使用python3&#xff0c;PyQt5&#xff0c;MySQL数据库搭建 主要功能&#xff1a; 用户注册、登录、修改密码、用户管理存储图书信息、采购增加和淘汰删除功能、租借功能实现图书采购、淘汰、租借功能。实现查询图书信息、采购和淘汰、库存、和租借情况实现统计图书的采购、库…

【FPGA】Verilog:全加器与半加器 | Full Adder | Half Adder

0x00 全加器(Full Adder) 值的加法运算逻辑电路,全加器不仅可以包括输入值,还可以将进位值纳入加法运算,是实现各种运算电路的基本运算电路。输出由 sum (S) 和 carry (C) 组成,加法运算中产生的进位称为 carry out ,从前一位传递过来并需纳入当前位加法运算的进位称为…

ElasticSearch学习笔记之一:介绍及EFK部署

1. 系统概述 The Elastic Stack&#xff0c;包括Elasticsearch、Kibana、Beats和Logstash&#xff08;也成为ELK Stack&#xff09; Elasticsearch&#xff1a;简称ES&#xff0c;是一个开源的高扩展的分布式全文搜索引擎&#xff0c;是整个Elastic Stack技术栈的核心。它可以…

【C++修行之道】类和对象(三)拷贝构造函数

目录 一、 概念 二、特征 正确的拷贝构造函数写法&#xff1a; 拷贝函数的另一种写法 三、若未显式定义&#xff0c;编译器会生成默认的拷贝构造函数。 四、编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了&#xff0c;还需要自己显式实现吗&#xff1f; 深拷…

项目资源管理

目录 1.概述 2.六个过程 2.1. 规划资源管理 2.2. 估算活动资源 2.3. 获取资源 2.4. 建设团队 2.5. 管理团队 2.6. 控制资源 3.应用场景 3.1.十个应用场景 3.2.软件开发项目 3.2.1. 资源规划 3.2.2. 资源分配 3.2.3. 资源获取 3.2.4. 资源优化 3.2.5. 资源监控与…

YOLOv10(4):损失(Loss)计算及其检测模型代码部分阅读

YOLOv10&#xff08;1&#xff09;&#xff1a;初探&#xff0c;训练自己的数据_yolov10 训练-CSDN博客 YOLOv10&#xff08;2&#xff09;&#xff1a;网络结构及其检测模型代码部分阅读-CSDN博客 目录 1. 写在前面 2. 双标签分配 3. 计算Loss的预备条件 &#xff08;1&a…

OpenCV-最小外接圆cv::minEnclosingCircle

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 函数原型 void minEnclosingCircle(InputArray points, Point2f& center, float& radius); 参数说明 InputArray类型的…

Codeforces Round 950 (Div. 3) 个人题解 (A~F1)

Codeforces Round 950 (Div. 3)个人题解(A~F1) 题解火车头 #define _CRT_SECURE_NO_WARNINGS 1#include <iostream> #include <vector> #include <algorithm> #include <set> #include <unordered_map> #include <cstring> #include <…

聚观早报 | 东风奕派eπ008将上市;苹果Vision Pro发布会

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 6月3日消息 东风奕派eπ008将上市 苹果Vision Pro发布会 特斯拉Model 3高性能版开售 小米14推送全新澎湃OS系统 …

ubuntu中彻底删除mysql (配置文件删除可选)

ubuntu中彻底删除mysql (配置文件删除可选) 对于此类即搜即用的分享文章&#xff0c;也不过多赘述&#xff0c;直接依次按照下面的操作执行即可&#xff1a; 一、删除 mysql 数据文件 sudo rm /var/lib/mysql/ -R二、删除 mysql 配置文件 sudo rm /etc/mysql/ -R三、查看 m…

基于 Spring Boot 博客系统开发(十三)

基于 Spring Boot 博客系统开发&#xff08;十三&#xff09; 本系统是简易的个人博客系统开发&#xff0c;为了更加熟练地掌握 SprIng Boot 框架及相关技术的使用。&#x1f33f;&#x1f33f;&#x1f33f; 基于 Spring Boot 博客系统开发&#xff08;十二&#xff09;&…