【精通Postman接口测试-完结】05-Postman通关收官!接口鉴权+接口加密+接口签名+Mock数据构造

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
🎯 你正在阅读「接口测试从入门到跑路」系列文章 🎯

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨

🔥 弹简特 个人主页

❄️ 个人专栏直通车:

靠热爱去书写自己,靠勇敢去书写生活!

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨


🌟 博主简介:


文章目录:


前言

这是 Postman 系列的最后一篇,主要整理接口测试中绕不开的几个知识点:鉴权、加密、签名和 Mock。

前面的笔记已经把 Postman 的基础操作、变量、断言、批量执行都过了一遍,本篇把剩下的鉴权方式对比、常用加密算法的代码实现、Sign 签名的生成逻辑以及 Mock 服务的搭建方法补齐,这样整个 Postman 接口测试的知识体系就完整了,那么我们开始吧~


一、Postman接口鉴权介绍

1、Cookie鉴权

1.1 什么是Cookie

Cookie不是缓存,是服务器生成并保存在客户端的一段文本信息,格式为字典(键值对)。它通常用于在Web项目中维持状态或传递数据,一般记录的是不重要的数据。当客户端第1次访问服务器时,服务器生成Cookie并通过响应头Set-Cookie返回给浏览器,浏览器将其保存;后续客户端再次访问时,会在请求头Cookie中自动带上之前保存的Cookie值。

1.2 Cookie里面有哪些键(Key)

  • name:Cookie的名称,用于标识该Cookie。
  • value:Cookie的值,存储具体的数据。
  • Domain:作用域,指定Cookie可被发送到哪些域名下。
  • Path:作用路径,指定域名下的哪些路径可以携带该Cookie。
  • Expire :生命周期,用于区分两类Cookie:
    • 时间持久级Cookie :设置了明确的过期时间(ExpiresMax-Age),在到期前即使关闭浏览器也会保留,到期后自动失效。
    • 会话级Cookie(Session Cookie):未设置过期时间,仅在当前浏览器会话期间有效,关闭浏览器后即被删除。
  • Size:大小,指Cookie所占的存储空间大小(通常以字节计)。

1.3 Cookie鉴权的原理

严格来说,Cookie本身不叫鉴权,它最初的设计目的是用于传递和记录统计数据,比如统计访问服务器的次数等不敏感信息。但在实际Web项目中,常通过Cookie携带会话标识(如Session ID)来实现鉴权,其工作流程如下:

  1. 首次访问生成Cookie :客户端第一次访问服务器时,服务器生成一个带有唯一标识的Cookie,并通过HTTP响应头Set-Cookie传输到客户端浏览器,浏览器将其保存。
  2. 后续请求自动携带Cookie :当同一客户端再次访问该服务器时,浏览器会在请求头Cookie中自动附带之前保存的Cookie值,服务器读取该Cookie即可识别用户或维持会话状态。

1.4 Postman里面如何实现Cookie鉴权

Postman可以充当浏览器的角色,自动处理Cookie。在发送请求时:

  • Postman会像浏览器一样,在首次收到Set-Cookie响应头后,自动存储Cookie。
  • 后续向同一域名发送请求时,Postman会自动在请求头Cookie中携带对应的Cookie值,无需手动设置。
    因此,使用Postman进行需要Cookie鉴权的接口测试时,只需要先发送一次带有登录或会话初始化的请求,让Postman获取并保存Cookie,之后对该域名下的其他接口请求便会自动完成Cookie鉴权。

1.5 案例演示

1)首先我们在Postman里面点击Cookies
2)在里面我们现在是看不到任何session的
3)现在我访问论坛首页
4)此时再次打开Cookies看里面,你会看到内容


浏览器也会自动的保存cookie,我们的Postman就是充当浏览器这样的一个角色自动保存的cookie。

5)接下来我们访问登录页面

在后续的请求中,浏览器也会自动带上Cookie值,Postman就是充当浏览器这样的一个角色,自动带上cookie值。

6)总结

总之举例子就是说明对于Postman我们测试人员不用去管 Cookie的存值和传递的过程,他会自动的为我们做这些事。

2、Session鉴权

2.1 什么是Session

Session也叫会话,指的是用户从登录到登出这一完整周期内与服务器之间的交互过程。在技术实现上,它表现为服务器在内存中为用户创建的一个专属数据存储空间。Session一般应用于Web项目,默认失效时间通常是半小时,具体时长由应用服务器决定。

2.2 Session里面一般存什么

Session存储在服务器端,通常用来保存一些需要保密的、与用户当前会话强相关的数据,例如:

  • 用户登录状态及唯一标识(如用户ID)。
  • 用户名、角色权限等核心身份信息。
  • 临时业务数据(如购物车内容、多步骤表单的中间数据)。

2.3 Session鉴权的原理

Session鉴权不能 单独完成,必须配合Cookie一起使用。SessionID本身只是一串唯一标识,它需要通过Cookie作为传输载体在客户端和服务器之间传递。

具体工作流程如下:

  • 第一步(登录) :客户端首次登录时,服务器验证用户名密码通过后,会在服务器内存中创建一个Session,其中保存该用户的身份信息,并生成一个唯一的SessionID。然后,服务器通过本次登录请求的响应头Set-Cookie,将包含此SessionID的Cookie传输到客户端浏览器。
  • 第二步(后续访问) :从登录成功后的第2次请求开始,客户端浏览器会根据Cookie的作用域规则,自动在请求头Cookie中携带包含SessionID的Cookie值。服务器接收到请求后,从中提取SessionID,并与自己内存中存储的Session清单进行对比。如果能找到匹配的有效Session,就读取其中的用户数据,完成身份鉴权。

2.4 Postman里面如何实现Session鉴权

Postman可以充当浏览器的角色,自带Cookie管理机制。利用这一特性,实现Session鉴权的步骤如下:

  1. 触发登录 :先发送一次正确的登录请求。Postman在收到服务器返回的Set-Cookie响应头时,会自动将含有SessionID的Cookie储存下来。
  2. 自动鉴权 :之后对同一域名(Domain)和路径(Path)下的业务接口发送其他请求时,Postman会像浏览器一样,自动在请求头Cookie中附带上之前存储的SessionID,与服务器端Session进行比对,从而完成无感鉴权,无需测试人员手动处理

2.5 详解Cookie和Session

对于Cookie和Session的详细解释可以参考博客 👇
Cookie和Session


3、Token鉴权

3.1 什么是Token

Token也叫令牌或鉴权码,是服务器生成并返回给客户端的一串字符串凭证。它通常用于无状态的接口鉴权,由开发人员在后端代码中设定生成规则和时效性(如2小时过期)。与Cookie和Session不同,Token不强制依赖浏览器的存储机制,它本质上是一个需要开发人员在前后端代码中显式处理的凭证。

3.2 Token里面一般存什么

Token(尤其是JWT格式)通常由编码后的字符串构成,其中可能包含:

  • 用户的唯一标识(如用户ID)。
  • 令牌的签发时间与过期时间。
  • 用户角色或权限范围。
  • 自定义的业务负载数据。

3.3 Token鉴权的原理

Token鉴权可以独立完成 ,不依赖于Cookie。它是否需要浏览器自动处理,取决于开发人员的实现方式:通常Token由开发人员主动保存在客户端的本地存储(如LocalStorage)或Cookie中,并在每次请求时手动取出附加到请求中。因此,在测试过程中,需要测试人员手动处理

工作流程如下:

  • 第一步(登录获取):客户端提交登录信息,服务器验证通过后生成一个Token,并保存到服务器数据库(或在无状态令牌中直接签发)。服务器会将此Token放在响应体(Body)中返回给客户端。
  • 第二步(后续访问):从第2次请求开始,客户端需要主动读取Token,并根据约定的鉴权模式将其附加到请求中进行传输。服务器收到Token后,会与数据库记录对比或解析校验令牌有效性,完成鉴权。

Token鉴权的传输形式(由开发人员定义,测试时需查阅接口文档确认):

  • 普通模式 :通过请求参数(Params)传递,如 ?token=xxx
  • Bearer模式 :在请求头(Headers)中传输,标准格式为 Authorization: Bearer <token值>

3.4 Postman里面如何实现Token鉴权

在Token鉴权中,Postman 不能 像处理Cookie那样自动存储和携带Token,需要我们测试人员手动处理

处理方式依据接口文档而定,主要在Postman的以下位置操作:

  • 若接口采用Bearer模式 (最常见):在请求的 Headers 标签页下添加键值对:
    • KeyAuthorization
    • ValueBearer + 空格 + Token的具体值。
      (注意:不要错误地写成 Authorization Bearer aaaa,这是不规范的格式;标准写法是 Authorization: Bearer aaaa,且 Bearer 作为值的一部分放在Header的Value里。)
  • 若接口采用普通模式 :在请求的 Params 标签页下添加参数,参数名(如 token)和值按接口文档填写。

操作总结 :测试时,需先调用登录接口并从响应体(Body)中手动复制Token值,然后粘贴到后续业务请求的 Headers 或 Params 中,或者使用我们的提取器将token设置为集合变量等操作,然后从集合变量中去取出。


3.5 详解Token

对于token的各种细节,可以参考博客 👇(总结得很详细,各种原理为你剖析
详解token


4、Cookie,Session,Token的区别

结合之前的讲解,将三者的核心区别对比如下:

维度 Cookie Session Token
本质定义 存储在客户端的一段小文本信息,格式为字典。 存储在服务器内存中的用户会话数据空间。 一个由服务器签发的加密字符串令牌。
存储位置 客户端(浏览器)。 服务器内存中。 通常存于服务器数据库或硬盘中,客户端则存在本地存储(LocalStorage)或Cookie里。
安全性 较低,数据直接暴露在客户端。 较高,核心数据在服务器端,客户端只保存一个无意义的SessionID。 较高,数据经过编码或加密,即使被截获也难以篡改,但需防范令牌泄露。
依赖关系 独立存在。 必须依赖Cookie,SessionID需要通过Cookie在客户端和服务器之间传输。 可以独立完成鉴权,不强制依赖Cookie。
传输方式 浏览器根据Domain和Path规则,自动通过Cookie请求头携带。 由浏览器通过Set-CookieCookie请求头自动处理,本质上传输的就是SessionID。 需要手动处理 ,开发或测试人员需手动将其添加到请求的ParamsHeaders (如Authorization)中。
大小限制 有大小限制,单个Cookie不超过4KB 无硬性大小限制,但会话数据过多会大量占用服务器内存,影响性能。 无硬性大小限制,但令牌过长会增加每次请求的传输负担。
生命周期 会话级 :关闭浏览器失效。 • 持久级 :在设置的Expires时间后失效。 由应用服务器控制,通常在一段时间无操作后失效(如30分钟)。 在签发时设定有效期,在约定的时间后失效(如2小时)。
Postman处理 Postman能像浏览器一样自动接收和携带,无需测试人员干预。 Postman能自动处理Cookie,从而实现SessionID的自动携带,无需测试人员干预。 Postman无法自动处理,需测试人员手动从登录接口响应中复制Token,并根据接口文档粘贴到后续请求的Headers或Params中。

总结一下

  • Cookie 是客户端的存储和传输机制,简单但直接。
  • Session 将秘密留在服务器,通过Cookie传递一把临时的"钥匙"(SessionID)来鉴权,原生支持浏览器。
  • Token 是一张自带信息的加密"身份证",不依赖Cookie和服务器存储,更灵活,尤其适用于前后端分离、移动端或跨域场景,但需要手动处理。

5、Postman中有的鉴权方式

  • Inherit auth from parent:从父节点继承鉴权验证

  • No Auth:没有鉴权

  • Basic Auth:基础验证 使用用户名和密码鉴权的

  • Bearer Token:持有者令牌验证

  • JWT Bearer:JSON Web Token验证

  • Digest Auth:摘要式验证

  • OAuth 1.0:签名过程验证

  • OAuth 2.0:签名过程,类似于Bearer token模式

  • Hawk Authentication:消息验证码验证

  • AWS Signature:亚马逊公有云的验证方式

  • NTLM Authentication:NTLM身份验证

  • API Key:API密钥验证

  • Akamai EdgeGrid:Akamai的边缘网格验证方式

  • ASAP (Atlassian):Atlassian的服务验证协议


二、Postman接口测试加密实战

1、接口加密基础

1.1 为什么需要接口加密

测试接口时,很多敏感数据(比如密码、手机号、支付信息)并不是明文传输的。被测系统为了防止数据被"裸奔"窃取,会要求客户端先按照约定算法加密,再把密文发给服务器。

我们在做接口测试时,95%以上的场景只需要按照算法加密出一条正确的密文,而不用去解密服务器的响应(除非要验证服务器返回的数据是否正确)。也就是说,测试人员主要是在模拟前端的加密行为。

验证加密结果对不对,可以借助在线工具(如 www.bejson.com)来交叉比对。

1.2 加密算法分类

从能不能逆回去的角度,加密算法大致分两类:

  • 单向加密(哈希)

    只能加密,不能解密。就像一个"指纹机",给同样内容永远产出同样的摘要,但通过摘要无法倒推出原文。

    常用于:存密码、文件完整性校验。

    代表算法:MD5、SHA系列、HMacSHA系列

  • 双向加密

    既能加密,也能解密。根据加/解密用的是不是同一把"钥匙",又分为:

    • 对称加密 :加密和解密用同一把密钥 。速度快,但双方都得先知道这个密钥。
      代表:Base64(严格说是一种编码)、AES、DES
    • 非对称加密 :有一对钥匙------公钥加密,私钥解密 。公钥可以公开,私钥打死也不给外人。
      代表:RSA。Postman 自带的 CryptoJS 库不支持 RSA,需要额外引入脚本。

2、Postman单向加密

单向加密直接在 Pre-request Script 里用 CryptoJS 调用,然后存成变量,在请求参数中引用。

在Postman中加密算法都是通过CryptoJS(译为加密 JS 库 )对象来完成的

2.1 MD5加密算法

MD5 生成固定 128 位(即 32 个字符)的哈希值。虽然现在不安全不建议存密码,但老系统中仍广泛使用。
加密算法的代码只需要保存起来,到时候需要的时候粘贴过去就行了,不要刻意去记
MD5加密算法如下:

javascript 复制代码
// 1. 准备要加密的原始数据
var rawText = "admin";

// 2. 调用 CryptoJS.MD5() 方法进行加密,并用 toString() 转换成十六进制字符串
var md5Hash = CryptoJS.MD5(rawText).toString();
// 结果类似:21232f297a57a5a743894a0e4a801fc3

// 3. 将加密结果存为全局变量,方便在请求参数里 {{md5_username}} 引用
pm.collectionVariables.set("md5_username", md5Hash);
2.1.1 实战练习
1)接口文档

简要描述:

MD5加密接口
请求URL:
http://116.62.63.211:5000/md5login
请求方式:

POST
参数:

参数名 必选 类型 说明 备注
username string 用户名:admin 用户名必须MD5加密处理
password string 密码:123 密码必须MD5加密处理

返回示例

java 复制代码
{"error_code":0,"message":"MD5加密登陆成功!"}

返回参数说明

参数名 类型 说明
message string success表示登陆成功
2)开始测试

a、如果不加密:请求失败

b、如果加密:首先要在请求之前把admin和123加密好,并存在集合变量中

js 复制代码
//加密用户名admin
var md5Username = CryptoJS.MD5("admin").toString();
//假面密码123
var md5Password = CryptoJS.MD5("123").toString();


//将结果存到集合变量中
pm.collectionVariables.set("md5_username", md5Username);
pm.collectionVariables.set("md5_password", md5Password);

c、从集合变量中去取出值取值使用{``{名字}}

2.2 SHA系列加密算法

SHA 家族比 MD5 更安全,可以提供更长位数的摘要,比如 SHA-256 就非常常用。

javascript 复制代码
// 以 "admin" 为例,演示不同 SHA 算法的调用

// SHA1(160位哈希值)
var sha1Hash = CryptoJS.SHA1("admin").toString();
console.log("SHA1:", sha1Hash);

// SHA3(最新标准,可输出不同长度,默认是 512 位)
var sha3Hash = CryptoJS.SHA3("admin").toString();
console.log("SHA3:", sha3Hash);

// SHA224 / SHA256 / SHA384 / SHA512 分别代表不同长度的输出
var sha224Hash = CryptoJS.SHA224("admin").toString();
console.log("SHA224:", sha224Hash);

var sha256Hash = CryptoJS.SHA256("admin").toString();
console.log("SHA256:", sha256Hash);

var sha384Hash = CryptoJS.SHA384("admin").toString();
console.log("SHA384:", sha384Hash);

var sha512Hash = CryptoJS.SHA512("admin").toString();
console.log("SHA512:", sha512Hash);

// 实际使用时,选一个算法即可,把结果存成变量(具体存为什么变量,根据需求来)
pm.collectionVariables.set("sha256_pwd", sha256Hash);

2.3 HMacSHA系列加密算法

HMac 在普通哈希的基础上加了一个密钥,相当于"带密码的哈希"。即使原文相同,密钥不同,结果完全不一样。

javascript 复制代码
// HMac系列函数的第一个参数是「原文」,第二个参数是「密钥」
var secretKey = "mashang";

// HmacSHA1
var hmacSHA1 = CryptoJS.HmacSHA1("admin", secretKey).toString();
console.log("HmacSHA1:", hmacSHA1);

// HmacSHA256(最常用)
var hmacSHA256 = CryptoJS.HmacSHA256("admin", secretKey).toString();
console.log("HmacSHA256:", hmacSHA256);

// HmacSHA512
var hmacSHA512 = CryptoJS.HmacSHA512("admin", secretKey).toString();
console.log("HmacSHA512:", hmacSHA512);

// 甚至还有 HmacMD5,虽然不推荐但用法一致
var hmacMD5 = CryptoJS.HmacMD5("admin", secretKey).toString();
console.log("HmacMD5:", hmacMD5);

// 把需要的一个结果存入环境变量,也可是集合变量(具体看需求)
pm.environment.set("hmac_sign", hmacSHA256);//存入环境变量
pm.collectionVariables.set("hmac_sign", hmacSHA256);//存入集合变量

3、Postman双向加密

双向加密中,我们不仅要会加密(模拟请求入参),有时候也要能解密(用来断言返回的密文数据)。

3.1 双向对称加密算法

Base64 编码(常被当成加密用)

Base64 其实不是加密,只是一种编码方式,可以把二进制数据转成纯文本。但它"可逆",看起来像加密,老系统里偶尔会用它传密码。

javascript 复制代码
// ========== 加密 ==========
// 1. 把需要编码的字符串转成 UTF-8 字节数组
var wordBytes = CryptoJS.enc.Utf8.parse("admin");

// 2. 用 Base64 编码该字节数组
var base64Str = CryptoJS.enc.Base64.stringify(wordBytes);
// 结果: "YWRtaW4="

// 3. 存入变量备用
pm.collectionVariables.set("base64_username", base64Str);

// ========== 解密 ==========
// 需要解密时,执行以下步骤
// 1. 将 Base64 字符串解析成字节数组
var decodedBytes = CryptoJS.enc.Base64.parse("YWRtaW4=");

// 2. 把字节数组再转回 UTF-8 字符串
var originalText = decodedBytes.toString(CryptoJS.enc.Utf8);
console.log("解密结果:", originalText); // 输出: admin
AES 对称加密

AES 是真正的加密算法,需要约定好密钥(Key)加密模式(如 CBC)初始向量(IV)

javascript 复制代码
// 定义密钥和初始向量(必须和服务器约定好,且长度通常为16字节)
var key = CryptoJS.enc.Utf8.parse("1234567890123456"); // 16位密钥
var iv  = CryptoJS.enc.Utf8.parse("1234567890123456"); // 16位IV

// 调用 AES 加密,传入原文和配置
var encrypted = CryptoJS.AES.encrypt("admin", key, {
    iv: iv,                         // 初始向量
    mode: CryptoJS.mode.CBC,       // 加密模式(CBC最常用)
    padding: CryptoJS.pad.Pkcs7    // 填充方式
}).toString();

// 结果是一长串 Base64 编码的密文,直接存入变量
pm.collectionVariables.set("aes_token", encrypted);

// ========== AES 解密 ==========
// 如果需要解密响应里的密文
var decryptedBytes = CryptoJS.AES.decrypt(encrypted, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
});
// 解密后是字节数组,转回原文
var decryptedText = decryptedBytes.toString(CryptoJS.enc.Utf8);
console.log("AES解密:", decryptedText); // admin
DES 对称加密

DES 跟 AES 用法类似,只是算法换成了 CryptoJS.DES,密钥长度一般是 8 字节。

javascript 复制代码
var desKey = CryptoJS.enc.Utf8.parse("12345678"); // 8字节密钥
var desIv  = CryptoJS.enc.Utf8.parse("12345678");

var encryptedDES = CryptoJS.DES.encrypt("admin", desKey, {
    iv: desIv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
}).toString();

pm.collectionVariables.set("des_pwd", encryptedDES);
Base64实战
1)接口文档

简要描述:

BASE64加密接口
请求URL:
http://116.62.63.211:5000/base64login
请求方式:

POST
参数:

参数名 必选 类型 说明 备注
username string 用户名:admin 用户名必须BASE64加密处理
password string 密码:123 密码必须BASE64加密处理

返回示例

json 复制代码
{"error_code":0,"message":"Base64加密登陆成功!"}

返回参数说明

参数名 类型 说明
message string success表示登陆成功
2)开始测试

a、如果你不加密,那么请求就会报错哦

b、在请求之前使用代码用Base64对admin和123进行加密

代码:

js 复制代码
/****对于用户名***/
//把需要编码的字符串转成 UTF-8 字节数组
var username = CryptoJS.enc.Utf8.parse("admin");
//用 Base64 编码该字节数组
var base64Username = CryptoJS.enc.Base64.stringify(username);

/****对于密码***/
//把需要编码的字符串转成 UTF-8 字节数组
var password = CryptoJS.enc.Utf8.parse("123");
//用 Base64 编码该字节数组
var base64Password = CryptoJS.enc.Base64.stringify(password);

//将结果存到集合变量中
pm.collectionVariables.set("base64_username", base64Username);
pm.collectionVariables.set("base64_password", base64Password);

c、使用{``{名字}}取出我们加密之后的值

3.2 双向非对称加密算法 ------ RSA(了解即可)

RSA 有一对钥匙:公钥(加密)私钥(解密) 。服务端把公钥给前端,前端用公钥加密后发送,服务端用自己的私钥解开。
但在 Postman 里,CryptoJS 不支持 RSA,不能直接一行代码调用。测试这类接口时,需要测试人员通过以下方式手动处理:

  • 引入第三方的 JS 库(如 forge),在 Pre-request Script 中编写更复杂的加密脚本。
  • 或者,用 Java/Python 等编写一个本地加解密工具,测试前调用工具生成密文,再粘贴到 Postman 里。

因此 RSA 加密的 Postman 实现并不在"精通"范围内,需要依赖脚本开发能力,所以这个我们就不举例子了,了解即可,我们的Postman不太支持。


4、加密实战小结

加密类型 算法例子 能否解密 Postman实现方式 关键点
单向加密 MD5, SHA, HmacSHA ❌ 不可解密 直接调用 CryptoJS.MD5/SHA...toString()后存变量 通常只加密入参;Hmac 需要额外提供密钥
对称加密 AES, DES, Base64(编码) ✅ 可解密 调用 CryptoJS.AES/DES.encrypt/decrypt 并配置密钥、IV等 注意密钥长度、加密模式和向量;Base64用 enc.Base64
非对称加密 RSA ✅ 可解密(私钥) CryptoJS 不支持,需引入 forge 等外部库编写脚本 需要开发提供公钥,测试时确保用正确的填充格式

Postman 加密通用套路:

  1. 在请求的 Pre-request Script 标签页写加密代码。
  2. 把密文存入变量,如 pm.environment.set("encryptedPwd", 密文);
  3. 在请求的 Params / Body 里用 {``{encryptedPwd}} 占位引用。

三、Postman接口测试接口签名实战

对于接口签名的详细解释,我们在之前的jmeter中介绍过,可参考博客 👇
精通jmeter之接口签名

这里就简单回顾一下👇

1、什么是Sign签名

Sign(签名)并不是一种独立的加密算法,而是由开发人员根据项目需要,自定义的一套参数组合与加密规则。它的作用是把请求中的核心参数,按照约定方式拼成一个字符串,再通过MD5等单向加密生成一个"防伪码"。

服务器收到请求后,会用相同的规则再算一次签名,然后与客户端传来的签名比对。如果不一致,就说明请求在传输过程中被篡改,或者签名秘钥不对,服务器会直接拒绝请求。

为什么需要Sign?

  • 防篡改:只要参数有一丁点变动,签名就完全不一样。
  • 防重放:签名中通常会加入时间戳和随机数(nonce),让攻击者无法拿同一个请求反复提交。
  • 身份识别 :签名前会拼入预先分配好的 appidappsecret,相当于给请求盖了个"项目章"。

2、主流Sign签名规则

虽然每家公司规则不同,但绝大多数Sign签名都遵循下面这套流程:

第1步:收集所有参数

把请求中的Query参数(?后面的)和Body参数(如表单、JSON)全部拿出来,准备参与签名。

⚠️ 动态参数除外:像 csrf_tokensigntimestamp 这些本身就是用于防伪或签名计算的参数,通常不参与签名。

第2步:按键名ASCII码升序排序

把所有参数按照参数名的字母/字符ASCII码从小到大排序。

  • 比如原顺序:{c:3, a:2, b:1}
  • 排序后变成:{a:2, b:1, c:3}

第3步:拼接成URL参数字符串

把排序后的参数名和值用 = 连接,参数之间用 & 连接。

  • 排序后的集合 → a=2&b=1&c=3

第4步:在字符串头部拼接 appidappsecret

这两个是项目分配好的身份标识,通常直接拼在最前面。

  • 拼接后:appid=admin&appsecret=123&a=2&b=1&c=3

第5步:在字符串尾部拼接随机数 nonce
nonce 是用来保证请求唯一性的流水号,防止重复提交,一般是一串10位以上的随机字符串。

  • 拼接后:appid=admin&appsecret=123&a=2&b=1&c=3&nonce=1234567890abcdef

第6步:在字符串尾部拼接时间戳 timestamp

时间戳通常精确到秒或毫秒,服务器只接受一定时间范围内的请求(如10分钟内),超时就失效。

  • 拼接后:appid=admin&appsecret=123&a=2&b=1&c=3&nonce=1234567890abcdef&timestamp=1683000000

第7步:进行MD5加密,并转为大写

对这个长字符串做一次MD5运算,然后把所有字母转成大写,这就是最终的签名 sign

  • 签名结果类似:F8E2A1B3C4D5E6F7A8B9C0D1E2F3A4B5

第8步:把 sign 放到请求头中发送

通常放到 Authorization 头或自定义的 Sign 头里,例如:

  • Sign: F8E2A1B3C4D5E6F7A8B9C0D1E2F3A4B5
  • Authorization: sign=F8E2A1...

接下里我们将上述的过程写成代码👇

3、在Postman中实操

3.1 接口描述

  • 接口地址POST http://127.0.0.1/wind/index.php?m=u&c=login&a=dorun
  • Body参数x-www-form-urlencoded):
    • username : lisi
    • password : 123456
    • csrf_token : {``{csrf_token}} ← 动态参数,不参与签名
    • backurl : http://127.0.0.1/wind/
    • invite : (没填,空值是否参与签名看规则)

假定这个项目的签名规则就是上面说的标准流程,并且约定:

  • appid = admin
  • appsecret = 123(根据实际项目填入)
  • 签名计算时排除 csrf_token
  • 最终签名放在请求头 Sign 里。

3.2 Sign 签名生成脚本

1、将以下代码完整粘贴到登录接口的 Pre-request Script 标签页。

javascript 复制代码
// ==================== Sign 签名生成脚本 ====================
// 规则说明:
//   1. 收集所有 Query 参数和 Body 参数(排除 csrf_token 等动态字段)
//   2. 将参数按 key 升序排列
//   3. 拼接为 key=value 的 & 连接字符串
//   4. 在最前面加上 appid=xxx&appsecret=xxx
//   5. 在最后面加上 nonce=随机数&timestamp=时间戳
//   6. 整个字符串做 MD5 加密,并转大写,得到 sign
//   7. 把 sign、nonce、timestamp 存入环境变量,供 Headers 使用

// -----------------------------------------------------------
// 【工具函数1】生成指定范围内的随机整数(用于 nonce)
// min:最小值,max:最大值
function getnonce(min,max){
    // Math.random() 返回 0-1 之间的随机小数
    // 乘以 (max - min + 1) 再 floor,得到一个 [min, max] 的整数
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

// 【工具函数2】将对象的 key 按照 ASCII 码升序排序,返回一个新对象
// 这样后续遍历对象拼接字符串时,顺序就是固定的
function objectsort(obj){
    // 取出所有 key 并排序
    var new_key = Object.keys(obj).sort();
    console.log("排序后的 key 顺序:", new_key);
    var arr = {}; // 新对象,顺序插入
    for(var i=0; i<new_key.length; i++){
        // 按排好的 key 依次拷贝 value
        arr[new_key[i]] = obj[new_key[i]];
    }
    return arr;
}

// ===========================================================
// 步骤1:获取项目分配好的 appid 和 appsecret(相当于用户名和密码)
var api_id = "admin";
var api_secret = "123";
console.log("appid:", api_id);
console.log("appsecret:", api_secret);

// ===========================================================
// 步骤2:获取当前时间戳
// 注意:这里原代码用的是 new Date().getTime(),返回的是 13 位毫秒级时间戳
// 很多后端签名校验使用 10 位秒级时间戳,若不一致会导致验签失败
// 建议与开发确认后,如需秒级,改为:Math.floor(new Date().getTime() / 1000)
var timestamp = new Date().getTime();
console.log("当前时间戳(毫秒):", timestamp);

// ===========================================================
// 步骤3:生成订单号 nonce(十位随机数字)
// 作用:保证每次请求的唯一性,防止重放攻击
var nonce = getnonce(1000000000, 9999999999);
console.log("nonce=" + nonce);

// ===========================================================
// 步骤4:收集需要参与签名的所有参数
// 4.1 获取 URL 问号后面的 Query 参数(例如 m=u&c=login&a=dorun)
var params_value = pm.request.url.query.members;
console.log("Query 参数:", params_value);
// params_value 是数组,每个元素形如 {key:"m", value:"u"}

// 4.2 获取 Body 中的参数(x-www-form-urlencoded 格式)
// request.data 在 Pre-request Script 中是已解析好的 body 对象
var body_value = request.data;
// 删除动态字段 csrf_token,因为它每次都会变,不应该参与签名
delete body_value['csrf_token'];
console.log("去除 csrf_token 后的 Body 参数:", JSON.stringify(body_value));

// 4.3 将 Query 参数转换为普通对象,方便合并
var queryObj = {};
if(params_value){
    params_value.forEach(function(item){
        // 只保留有值且非空的参数(空值不参与签名)
        if(item.value){
            queryObj[item.key] = item.value;
        }
    });
}

// 4.4 合并 Query 和 Body 参数(Body 优先级更高,可覆盖同名参数)
var allParams = {};
// 先放入 Query 参数
for(var k in queryObj){
    allParams[k] = queryObj[k];
}
// 再放入 Body 参数(有同名的 key 会覆盖)
for(var k in body_value){
    // 只保留有值的参数,并且排除可能残留的 sign、timestamp、nonce 等动态字段
    var excludeKeys = ['sign', 'timestamp', 'nonce'];
    if(body_value[k] && excludeKeys.indexOf(k) === -1){
        allParams[k] = body_value[k];
    }
}
console.log("合并后的待签名参数:", JSON.stringify(allParams));

// ===========================================================
// 步骤5:将合并后的参数按 key 进行升序排序
var sortedParams = objectsort(allParams);
console.log("排序后的参数:", JSON.stringify(sortedParams));

// ===========================================================
// 步骤6:把排序后的参数拼接成 "key=value&key=value" 格式的字符串
var paramStr = '';
for(var k in sortedParams){
    paramStr += k + '=' + sortedParams[k] + '&';
}
// 去掉末尾多余的 &
if(paramStr.endsWith('&')){
    paramStr = paramStr.slice(0, -1);
}
console.log("参数字符串:", paramStr);

// ===========================================================
// 步骤7:拼接待签名的完整原始字符串
// 规则:appid=xxx&appsecret=xxx&[参数字符串]&nonce=xxx&timestamp=xxx
var rawStr = 'appid=' + api_id + '&appsecret=' + api_secret;
if(paramStr){
    rawStr += '&' + paramStr;
}
rawStr += '&nonce=' + nonce + '&timestamp=' + timestamp;
console.log("待签名原始串:", rawStr);

// ===========================================================
// 步骤8:计算 MD5 哈希,并转成大写,作为最终签名 Sign
var sign = CryptoJS.MD5(rawStr).toString().toUpperCase();
console.log("生成的 Sign:", sign);

// ===========================================================
// 步骤9:将 sign、nonce、timestamp 存入 Postman 环境变量
// 这样在请求的 Headers 中就可以通过 {{sign}} 等方式引用
pm.environment.set("sign", sign);
pm.environment.set("nonce", nonce);
pm.environment.set("timestamp", timestamp);
console.log("环境变量已设置:sign, nonce, timestamp");


注意:代码直接复制就行,我们也可以问AI辅助我们提效。

2、在 Headers 中添加一行:Key: SignValue: {``{sign}}


四、Postman接口测试Mock

1、什么是Mock

Mock译为模拟,Mock就是模拟数据,Mock 服务,本质上就是通过构造假的接口返回数据,来替代真实的后端响应。这样一来,前端同学在开发功能、搭建模块时,就无需苦等真实接口就绪,可以完全脱离对后端数据的依赖。前后端由此得以同步推进,从而显著缩短整体的项目开发周期。

2、Postman中如何Mock数据

1)第一步:选择Mock服务


2)构造Mock服务

比如Mock数据如下:

js 复制代码
{
    "tags": [
        {
            "id": 1,
            "name": "每天一罐可乐星人",
            "count": 0//此标签下粉丝数
        },
        {
            "id": 2,
            "name": "星标组",
            "count": 0
        },
        {
            "id": 127,
            "name": "广东",
            "count": 5
        }
    ]
}

3)点击变量可以看到我们构造的请求URL

4)测试获取Mock数据

URL中的ip直接{``{url}}获取

结果:


或者URL路径我们自己复制

结果:


五、补充两个函数

1、时间戳函数

js 复制代码
// 获取当前时间戳(毫秒级,13位)
// Date.now() 返回从 1970年1月1日 00:00:00 UTC 到当前时刻的毫秒数
var ts = Date.now();
console.log("当前时间戳(毫秒):", ts);

// 如果需要秒级时间戳(10位),除以 1000 后向下取整
var tsSeconds = Math.floor(Date.now() / 1000);
console.log("当前时间戳(秒):", tsSeconds);

2、使得请求等待三秒访问的延时函数

js 复制代码
// 定义 sleep 函数,参数 milliseconds 表示要等待的毫秒数
const sleep = (milliseconds) => {
    // 记录开始等待时的时间戳
    const start = Date.now();
    // 循环检查当前时间,直到超过预设的等待时长才退出
    // 注意:这种写法会阻塞当前线程,但 Postman 沙箱环境允许这样用
    while (Date.now() <= start + milliseconds) {}
};

// 调用示例:等待 3 秒(3000 毫秒)
console.log("开始等待 3 秒...");
sleep(3000);
console.log("等待结束,继续执行后续请求");

OK,到此~ 我们的精通Postman也就告一段落了


六、写在最后

兄弟们,到这里咱们 精通 Postman 接口测试就完结撒花了 🌸🌸🌸

从最开始的 Postman 安装配置,到变量体系、请求构建、断言提取,再到本篇的鉴权加密鉴权签名 Mock ------ 一路走过来,咱们把 Postman 接口测试的完整技能树都点亮了。

最后,要感谢每个点赞、评论、催更的兄弟 ------ 没有你们的正反馈,这个系列很难坚持到完结 ❤️

工具会变,但测试思维和方法论不会过时。Postman 的终点不是结束,是我们自动化测试路上的新起点。

下一系列见咯,兄弟们~~


相关推荐
麦科信仪器1 小时前
便携、专业 | 12bit硬核高精 | 麦科信 AHO1 系列汽车示波器正式发布!
测试工具·汽车·示波器·制造·安全性测试·测量
yzx9910132 小时前
二手交易平台智能客服机器人——基于规则引擎与 Selenium 的自动回复系统
selenium·测试工具·机器人
神州数码云基地2 小时前
AI 驱动的自动化安全测试工具--Strix
运维·人工智能·功能测试·测试工具·自动化
介一安全2 小时前
【Web安全】AI自动化实现前端加密算法逆向分析
测试工具·ai·自动化·逆向·安全性测试
老神在在0012 小时前
博客会话维持方式总结
postman·token·session
测试员周周11 小时前
【AI测试智能体】为什么传统测试方法对智能体失效?
开发语言·人工智能·python·功能测试·测试工具·单元测试·测试用例
阿斯加德D15 小时前
PCL2下载我的世界minecraft Java版启动器2026最新版分享
测试工具·游戏·游戏程序
小新同学^O^18 小时前
简单学习--> Selenium自动化测试
学习·selenium·测试工具
Apifox.1 天前
Apifox 近期更新|AI Agent Debugger、A2A Debugger、Postman API 导入、Ask AI 侧边栏对话
前端·人工智能·后端·测试工具·测试用例·postman