资讯详情

Postman接口测试实战:用Pre-request Script动态生成签名与token

发布时间:2026/10/2 3:50:53

500+
企业客户服务经验
120+
行业领域内容覆盖
3000+
原创页面设计沉淀
98%
客户满意度

Postman接口测试实战:用Pre-request Script动态生成签名与token

做接口测试最烦的事情是什么不是接口返回 500而是每次发送请求之前都要手工改参数时间戳不能重复、nonce 要随机、token 得从登录接口拿、sign 还要按规则重新算。以前我都是打开请求点开 Body 和 Headers 逐个改改完测试一次服务端一校验签名失败又得从头来一遍。后来我把 Postman 的变量和 Pre-request Script 用起来以后这类参数全部可以在请求真正发出去的瞬间自动处理好。这篇内容我就围绕“接口测试前对请求参数做自定义处理”这个主题讲讲我在实际项目里怎么用 Postman 做动态参数以及哪些坑最容易踩。1. 从“签名无效”的报错说起为什么请求参数需要自定义处理我刚接触 Postman 做接口测试时犯过一个特别蠢的错。当时要测一个结算接口请求头里要求带appId、timestamp、nonce、signbody 里还有一个订单号。为了省事我把这些参数全部写死在请求里第一次点击发送服务端正常返回第二次点击直接给我抛了一个“签名无效”。我检查了半天最后才发现问题根本不是签名算法写错而是时间戳没变、nonce 也没变。服务端做了防重放校验它发现两次请求的签名参数一模一样直接当重复请求拒绝了。这个案例很好地解释了接口测试中的参数不是所有东西都适合写死。我们需要在请求发送之前让一部分参数根据当前时间、当前环境、前序接口的返回结果动态生成再把生成的正确值塞到请求里。这个动作就是标题里说的“请求参数的自定义处理”。1.1 三类请求参数处理的思路完全不同日常接口测试中请求参数大概可以分成三类固定参数比如分页大小pageSize20、固定渠道号channelandroid这些值短时间内不会变写死或者用变量存起来都行。随请求变化的参数比如时间戳、随机字符串、UUID、当前登录用户 ID。这类参数每次请求都应该不一样必须动态生成。依赖其他接口才能拿到的参数比如先调登录接口拿到token再把它传给后续需要鉴权的接口或者从创建订单接口返回里拿到orderId再传给支付接口。这类参数必须从前一个接口的响应中提取再注入到当前请求。如果第一类参数写死问题不大但第二类和第三类还用手工改效率会非常低而且特别容易出错。尤其是签名类接口参数之间互相校验你只要漏改一个字段服务端就给你脸色看。1.2 自定义处理其实分三层Postman 里对参数的自定义处理从简单到复杂可以分为三个层次第一层是“变量占位符替换”。在请求的任何位置写{{变量名}}Postman 发送请求前会用对应的变量值把它替换掉。这个方案适合处理固定参数和环境切换比如{{baseUrl}}、{{token}}。第二层是“内置动态变量”。Postman 自带了一批动态变量比如{{$timestamp}}、{{$randomInt}}、{{$guid}}。你把参数值直接写成{{$randomInt}}每次发送前都会生成一个新的随机整数不需要写任何脚本。这一层适合快速生成随机数、随机 UUID、当前时间戳等简单场景。第三层才是真正意义上的“自定义处理”利用 Pre-request Script预请求脚本在请求发出前执行一段 JavaScript动态计算参数、拼接签名、修改请求头和请求体。这也是本文的核心内容适合处理签名、加密、接口关联等复杂场景。先用第一层和第二层能解决 60% 的问题剩下 40% 的复杂场景基本都要靠第三层。下面我按实际使用频率一个个展开讲。2. 先打地基用环境变量和全局变量把固定参数抽出来很多新手在用 Postman 时喜欢直接在 URL 里写死http://192.168.1.10:8080/api/login。开发的时候可能没什么感觉但等你要把同一套接口用例从测试环境切到预发布环境时就痛苦了所有 URL 都要手动改一遍。正确做法是用环境变量把这些容易变的部分抽出来。2.1 环境变量的创建与变量优先级在 Postman 右上角有个环境选择器点击它可以进入环境管理界面。你可以新建一个“测试环境”在里面添加键值对比如baseUrlhttp://192.168.1.10:8080usernametest_userpassword123456然后在请求 URL 里写成{{baseUrl}}/login在 body 里写{{username}}、{{password}}。切换环境时只需要切换环境选择器所有请求都会自动使用新值。这里要提醒一个关键点变量作用域有优先级。Postman 的环境变量、全局变量、集合变量是可以重名的重名时也不是谁的都能随便覆盖谁。实际生效顺序从高到低大致是Pre-request Script 中用pm.variables.set设置的局部变量数据文件里当前行的字段运行时注入环境变量集合变量全局变量我遇到过一种情况环境变量里存了一个token全局变量里也存了一个token结果环境变量那个值过期了全局变量里的是新值但请求一直优先读取环境变量导致接口一直 401。后来才明白环境变量优先级比全局变量高这种情况必须去环境变量里改或者干脆删掉其中一个避免给自己挖坑。2.2 把 baseUrl 和公共请求头抽成变量固定参数不只是 URL还包括公共请求头。很多项目会在请求头里统一带X-App-Id、X-Api-Version这类字段。如果在每个请求里都手动填一遍一旦版本号升级你就是全组最忙的人。推荐做法是在集合级别统一处理。打开集合的“Pre-request Script”面板写一段通用逻辑// 集合级预请求脚本给集合下所有请求统一加公共请求头 pm.request.headers.upsert({ key: X-App-Id, value: 10001 }); pm.request.headers.upsert({ key: X-Api-Version, value: 2.0 });这样集合里每个请求发送前都会自动带上这两个请求头。如果你已经在某个请求里手动添加了同名 header脚本里的upsert会覆盖它如果不想被集合级脚本覆盖就要把请求级 header 的值也做成变量让脚本读取同一个变量。2.3 变量命名的隐性雷区变量命名看起来是小问题实际踩坑的人不少。我见过有人在环境变量里存了baseUrl又在全局变量里存了一个baseUrl结果切换环境后 URL 完全没变排查半天才发现是全局变量把环境变量顶掉了一部分。所以建议制定一个简单规则环境相关的配置只放环境变量全局变量只放跨环境都不变的公共配置。另外pm.environment.set(token, xxx)这种写法会实时修改当前环境变量的值。如果多个人共用一个环境配置你跑完测试后 token 会留在环境里下一个人拿到的可能是旧 token。建议在运行集合前先做一次清理// 集合级预请求脚本里先清掉脏数据 pm.environment.unset(token); pm.environment.unset(sign);不要觉得多余接口测试里最隐蔽的问题往往是残留变量导致的。3. 主角登场Pre-request Script 修改请求参数的正确姿势变量占位符能解决一部分问题但遇到“把请求里已有的参数读出来加工一下再放回去”这种需求就得让 Pre-request Script 直接操作当前请求对象了。Pre-request Script 本质上是在请求发送前执行的一段 JavaScript。你可以在里面读请求当前的 URL、headers、body修改它们也可以生成新值存到变量里。我常用的三个核心操作对象是pm.request.url.query、pm.request.headers和pm.request.body。3.1 修改 URL Query 参数假设你的请求 URL 是{{baseUrl}}/api/order?pageSize20你想在发送前动态追加一个traceId并覆盖pageSize可以这样写// 在 URL 查询参数里新增一个参数 pm.request.url.query.add({ key: traceId, value: TRACE_ Date.now() }); // 如果同 key 已存在用 upsert 覆盖 pm.request.url.query.upsert({ key: pageSize, value: 50 }); // 删除指定参数 pm.request.url.query.remove(debug);这里最容易踩的坑是你已经在 URL 输入框里写死了?pageSize20又在脚本里执行add({ key: pageSize, value: 50 })最后发出去的请求会变成?pageSize20pageSize50服务端拿到哪个值完全看解析策略。所以在脚本里处理已有参数时尽量用upsert而不是add。3.2 修改请求头请求头的修改逻辑和 URL 查询参数类似。比如你要在发送前自动给请求加一个鉴权头const accessToken pm.environment.get(token); pm.request.headers.upsert({ key: Authorization, value: Bearer accessToken });用upsert的好处是如果请求里已经有Authorization头它会覆盖如果没有它会新增。另外一个常见需求是删掉某个请求头。有时候服务端会根据User-Agent返回不同的结果测试时你想临时去掉它可以执行pm.request.headers.remove(User-Agent);3.3 修改请求 BodyBody 的修改比 URL 和 header 要复杂一些因为 Body 分好几种模式raw原始文本/JSON、urlencoded表单、form-data表单文件混合。如果是 raw JSON最稳的方式是先把原始内容解析成对象改完再序列化回去// 假设请求 Body 是 JSON 格式 const bodyObj JSON.parse(pm.request.body.raw); bodyObj.orderNo ORDER_ Date.now(); bodyObj.timestamp Date.now(); pm.request.body.update({ mode: raw, raw: JSON.stringify(bodyObj), options: { raw: { language: json } } });这里我特别想说一下很多人直接写pm.request.body.raw ...虽然也能改但不会自动更新 Body 的类型设置。最后发送时可能变成纯文本服务端解析 JSON 直接失败。用pm.request.body.update并带上options.raw.language json才能保持 JSON 请求的格式。如果是urlencoded表单操作方式是类似的pm.request.body.update({ mode: urlencoded, urlencoded: [ { key: username, value: test_user }, { key: timestamp, value: Date.now() } ] });注意它是数组结构传参时要写成一个数组而不是一个对象。3.4 修改前先读取别把原来的值弄丢了有时候你要在原来的参数值基础上做加工而不是直接生成新值。比如请求 URL 里本来就有orderId你需要把它取出来和小数点运算后再放回去。可以用const orderId pm.request.url.query.get(orderId); const newOrderId PRE_ orderId; pm.request.url.query.upsert({ key: orderId, value: newOrderId });注意pm.request.url.query.get(orderId)拿到的是解码后的值。如果原始值里包含%或这类 URL 编码字符你读出来的可能和 URL 上看到的并不完全一样。遇到这种场景建议直接用变量拼接不要过度依赖读取原始 URL 文本。4. 实战落地时间戳、随机字符串、签名和 token 依赖的完整套路前面讲的都是操作方法这一节我把真实业务里最常遇到的三种处理套路完整写出来。这些代码我都在生产项目里用过你可以直接复制改一改。4.1 时间戳 nonce MD5 签名的标准写法很多服务端接口为了避免重放攻击要求在请求头带timestamp、nonce、sign。其中sign通常是把若干参数按规则拼接后做 MD5 或 SHA 加密。用 Pre-request Script 实现如下const timestamp Date.now(); const nonce Math.random().toString(36).slice(2, 10); // 按服务端约定拼接字符串 const appKey your_app_key; const appSecret your_app_secret; const signSource appKey${appKey}timestamp${timestamp}nonce${nonce}secret${appSecret}; const sign CryptoJS.MD5(signSource).toString().toUpperCase(); pm.variables.set(timestamp, timestamp); pm.variables.set(nonce, nonce); pm.variables.set(sign, sign);然后在请求头里把timestamp、nonce、sign的值分别写成{{timestamp}}、{{nonce}}、{{sign}}。这样每次发送请求前脚本都会先算出一组新的时间戳、随机字符串和签名再发送。你不需要再手工改任何东西。这里要提醒一句Postman 沙箱自带CryptoJS可以直接用MD5、SHA1、SHA256、HmacSHA256这些方法。如果你的项目用的是其他加密方式比如 AES、RSA那就要在脚本里引入第三方库或者让后端同学先把最终串生成好。4.2 登录 token 的传递与刷新token 依赖是接口测试中最常见的关联场景。登录接口返回一个 token后续每个需要鉴权的接口都要带上它。如果手工从登录响应里复制 token再粘贴到其他请求那测三个接口还行测三十个接口就是灾难。正确做法是分两步第一步在登录请求的 Tests 脚本中把响应里的 token 提取出来const responseBody pm.response.json(); if (responseBody.code 0 responseBody.data.token) { pm.environment.set(token, responseBody.data.token); }第二步在后续请求的 Authorization header 或鉴权参数里直接写{{token}}。这样当你先登录、再跑其他接口时token 会被自动更新。如果你想让整个流程自动化可以把登录接口和业务接口放在同一个集合里用 Collection Runner 按顺序执行。关于这个套路有一个很容易被忽视的细节token 的提取脚本写在 Tests 里不是写在 Pre-request Script 里。因为 Token 必须在接口响应返回后才能拿到Tests 是响应返回后执行的而 Pre-request Script 是请求发送前执行的。有些新手把提取逻辑写错了位置然后在 Pre-request Script 里读不到 token就怀疑是 Postman 出了问题。4.3 需要二次编码或加密的参数还有一种典型的自定义处理场景请求参数不是直接明文而是需要经过 Base64 编码、URL 编码或者做一层简单加密。比如某些接口要求把整个 body 做 Base64 后放到data字段里const payload { username: pm.variables.replaceIn({{username}}), timestamp: Date.now() }; const encoded btoa(unescape(encodeURIComponent(JSON.stringify(payload)))); pm.variables.set(encodedData, encoded);请求 body 中只需发送{ data: {{encodedData}} }。btoa是 Postman 沙箱支持的编码方法但中文直接 btoa 会报错所以要先encodeURIComponent处理一下再转。这个细节很多教程不会写到你如果直接拿中文测试很容易在这里卡住。5. 数据驱动与批量/并发场景让每个请求的参数都不一样处理完单接口的动态参数下一步通常是批量场景。比如你同时接了十个服务端接口测试要求十个并发请求的 POST 参数各不相同这在 Postman 里怎么做答案是用数据文件做参数驱动。5.1 用 CSV/JSON 数据文件实现参数差异化Collection Runner 运行集合时可以指定一个 CSV 或 JSON 数据文件。每一行数据对应一次迭代发送请求前当前行的字段会作为{{变量名}}替换到请求里也可以在脚本中通过data.字段名读取。假设数据文件users.json内容如下[ { username: user01, age: 20 }, { username: user02, age: 21 }, { username: user03, age: 22 } ]请求 body 写成{ username: {{username}}, age: {{age}} }然后在 Collection Runner 里选择这个 JSON 文件迭代次数设为 3Postman 就会自动跑三次每次使用不同参数。这样写出来的接口用例天然就具备“每个请求参数都不一样”的能力。如果需要在脚本里对当前行的数据做二次加工在 Pre-request Script 中可以直接读取const username data.username; const age data.age; pm.variables.set(fullName, username _ age);这个data对象只存在于 Collection Runner 执行期间。你在单个请求的 Send 按钮点击时它是没有值的所以不要单独调试单个请求时用它否则脚本会报错。5.2 并发或批量运行下共享变量冲突怎么办这里必须说一个很多人踩过的坑批量跑用例时如果用同一个环境变量存 token并且多个请求同时修改它最后发出去的请求可能会带错 token。原因很简单环境变量是全局共享的请求 A 和请求 B 同时执行时A 把 token 改成了 A 的B 又把它改成了 B 的最后 A 真正发送时header 里取到的可能是 B 的 token。解决办法有几个尽量让每个请求自己独立生成所需参数不依赖共享环境变量。比如签名用的随机字符串和时间戳直接在各自请求的 Pre-request Script 里生成并写入局部变量。在批量执行时把 token 等共享信息从数据文件里读出来而不是从环境变量里读。如果确实需要登录态优先在集合级脚本里先执行一次登录把 token 存好再让业务请求引用但要注意先在集合脚本中清掉旧的 token避免脏数据。另外Postman 本身并不是为高并发压力测试设计的工具Collection Runner 默认是串行执行。你更多是把数据驱动当成“参数差异化”的解决方案而不是真正的并发压测。如果你需要完全意义上的并发请求一般会把同样的数据文件和集合丢给 JRater 或 Newman 这类工具去跑Postman 这边重点是把参数逻辑处理干净。6. 发送前如何确认参数真的改对了调试与验证实操脚本逻辑能跑通不等于发出去的请求是对的。很多时候脚本本身没有报错但算出来的签名还是错的、参数名还是拼错了。所以最后一定要养成“发送前确认最终参数”的习惯。6.1 用 Postman Console 检查最终发出的参数Postman 自带一个 Console可以查看每次请求实际发出的 URL、Headers 和 Body。打开方式是菜单栏 View - Show Postman Console或者直接按快捷键 Ctrl Alt CWindows/ Cmd Option CMac。在 Pre-request Script 里执行console.log()可以在 Console 里输出关键信息console.log(最终签名值: , sign); console.log(最终请求 URL: , pm.request.url.toString()); console.log(当前请求头: , pm.request.headers);然后点击 Send打开 Console在 Request 面板里就能看到最终发出去的完整请求。这一步基本能定位 90% 的“脚本改了但没改对”问题。6.2 借助 postman-echo 反向验证有些时候你不想直接打真实服务端只想确认参数有没有被正确自定义处理。这时可以用 Postman 官方提供的 echo 服务。比如你在 Pre-request Script 里处理了一堆 query 参数想确认它们最终真的是否被带上了可以把请求 URL 临时改成https://postman-echo.com/get然后看响应体里的args字段它会原样返回服务端收到的 query 参数。如果是 POST 请求可以用https://postman-echo.com/post响应体会返回json、data、form等字段这样你能一眼看出 body 里到底发了什么。这个方法特别适合调试签名算法先用 echo 服务确认参数格式再把 URL 换回真实环境。6.3 用 Tests 断言防止参数被静默改错另一个有效手段是在 Tests 里加入断言。Tests 虽然是请求响应之后执行的但它可以帮你自动校验“自定义处理是否生效”。比如你给请求设置了动态时间戳可以在 Tests 里判断当前发送的时间戳是否和请求成功时的响应相匹配pm.test(请求参数没有被改错, () { pm.expect(pm.response.code).to.be.oneOf([200, 201]); });更实用一点如果服务端会把你上传的参数原样返回你可以直接断言返回里的字段和你脚本里生成的变量一致。比如脚本里生成sign响应体里返回data.authResult你可以const res pm.response.json(); pm.test(sign 与服务端验证一致, () { pm.expect(res.data.authResult).to.equal(SUCCESS); });这样一旦参数处理有问题测试会直接失败而不是让你傻傻地盯着接口报错信息猜原因。我在实际项目里的习惯是每增加一个动态参数第一件事先在 Pre-request Script 里console.log打印一遍再用 echo 请求跑一次最后才接真实接口。等整个集合都稳定了再把 console.log 注释掉保持脚本干净。花这几分钟能省掉后面一整个下午的排查时间。接口参数的自定义处理本质上就是让 Postman 在“点击发送”到“请求真正出去”之间多走一段确定性逻辑而这套逻辑一定得在你自己可控的范围内。
热门专题

继续阅读更多专题内容

围绕企业服务、数字化转型与官网运营的常青话题,持续输出深度内容

企业官网建设指南 企业托管服务模式 财税政策与解读 企业数字化转型 官网SEO与获客 网站安全与运维
配套服务

读完这篇文章,了解更多服务

从整站搭建到SEO布局,17项核心服务助您打造高转化的企业官网

01

企业托管整站搭建

从信息架构到栏目预留,搭建可生长的企业站点骨架,每个页面独立原创设计。...

了解详情
02

规整可信网页设计

雪地靴温暖风原创设计,金属铜线条贯穿全页,拒绝通用模板与AI流水线。...

了解详情
03

企业服务SEO布局

关键词体系与语义化结构,从建站源头为搜索排名而生。...

了解详情
04

业务预约咨询表单

多场景表单与线索收集体系,把访问流量转化为可追踪的销售线索。...

了解详情
05

企业服务站点运维

安全巡检、数据备份与内容更新支持,全年守护网站稳定运行。...

了解详情
06

全终端商务适配

电脑、平板、手机一致呈现,移动端体验与转化同样出色。...

了解详情
需要专业建议?

让专业顾问为您解读行业趋势

关于企业官网建设、SEO获客与数字化转型的任何疑问,欢迎一对一咨询我们的专业顾问。