JMeter请求头设置全攻略:从基础配置到动态Token与签名

发布时间:2026/10/1 6:25:22
JMeter请求头设置全攻略:从基础配置到动态Token与签名
做接口测试或者压测的时候你有没有遇到过这种情况后端日志一直报参数缺失、报必要字段校验不过可你在JMeter里明明把参数都填齐了。排查到最后才发现问题根本不出在参数而是请求头“少了东西”——Content-Type不对、没带Token、User-Agent被识别成爬虫。这篇文章就把JMeter设置请求头的完整思路和详细步骤梳理一遍覆盖从基础配置、作用域规则到Token动态注入、签名Header的生成再到常用报错速查基本是一线干活会用到的东西。1. 请求头究竟是什么搞懂它就不用乱试了1.1 请求头的构成与工作原理HTTP协议里的请求其实分三大部分请求行、请求头、请求体。请求头是夹在中间的一堆键值对主要告诉服务器“我是谁、我要什么格式、我带了什么凭证”。很多人刚开始接触时觉得它就是个固定模板直接抄就行但实际排查问题时就会发现能不能调通接口很大概率就取决于请求头发得对不对。举个例子你用一个HTTP请求采样器往后端POST了一段JSON数据可后端一直接收不到参数十有八九就是Content-Type没设置成application/json。服务端看到默认的application/x-www-form-urlencoded就按表单去解析解析不出来自然给你返回报错。所以搞懂请求头的本质不是让你背HTTP协议而是让你在排错时有方向。JMeter发送HTTP请求时会默认带一批请求头比如User-Agent、Accept、Connection等。如果你需要自定义常规做法是添加“HTTP信息头管理器”。它本质上就是个键值对列表你在里面填什么JMeter发出请求时就会把对应的请求头带上。1.2 JMeter中设置请求头的几种方式设置请求头不是只有一种方法我平时用下来主要分为三种各自适用不同场景。第一种是直接用HTTP信息头管理器这也是最常用、最直观的方式。适合配置固定不变的请求头比如Content-Type、固定Token、固定的User-Agent。操作简单测试计划里哪个节点需要就加在哪里作用域由层级决定这个后文会细说。第二种是用HTTP请求自带的一些属性间接控制请求头。比如勾选了“Use multipart/form-data”后JMeter会自动生成multipart/form-data的Content-Type并自动带上boundary参数再比如通过HTTP请求的“Parameters”传参时JMeter也会自动生成application/x-www-form-urlencoded。这种方式不需要手动填请求头但前提是你得明白它背后自动生成了什么否则一旦遇到接口对Header有强校验的情况就会一头雾水。第三种是用JSR223预处理脚本动态生成请求头。当请求头的内容需要实时计算或者加密比如OAuth2的签名、时间戳、加密后的Token这种方法最合适。在JSR223 PreProcessor脚本里可以直接给vars.put(headerName, headerValue)然后HTTP信息头管理器里引用${headerName}变量。这块在第四章我会给完整实例。2. HTTP Header Manager实操从添加元件到请求成功2.1 完整操作步骤先说最关键的添加步骤做一次完整的演示。打开JMeter在测试计划上右键选择“添加” - “配置元件” - “HTTP信息头管理器”。这样就创建了一个配置元件。名字可以改成“固定请求头”之类的方便多人协作时识别。接着在右侧的HTTP信息头管理器面板中点击“添加”按钮会出来一行Name和Value输入框。Name那列填请求头的名称比如Content-TypeValue那列填它的值比如application/json;charsetUTF-8。可以添加多行每一行代表一个请求头。如果是从浏览器开发者工具或Charles里复制的请求头可以在面板下方的“从剪贴板添加”按钮粘贴进来JMeter会自动按行拆分这个功能在调试真实场景时特别好用。添加完之后需要决定它的作用范围。如果放在测试计划这一级那这个测试计划下所有HTTP请求都会自动带上这组请求头。如果放在某个线程组下面那就只对这个线程组里的请求生效。如果挂在某个HTTP请求采样器下面那只对那一个请求生效。这一点非常重要很多人在测试计划级加了一个请求头后面在子级又加了一个同名的导致实际发送的请求头和自己预期不一致。2.2 作用域与生效顺序JMeter的配置元件作用域是继承制。子级没有配置时自动向上查找父级配置子级也配置了同名请求头时以子级为准。同一级别内多个HTTP信息头管理器中的同名请求头后执行的会覆盖前面的。这个机制其实和日常工作中查资料有点像先从最近的书签里找找不到就去收藏夹翻找到就用最近的。理解了这一点你就能猜出报错的大致位置了。举个例子测试计划级我设了一个全局的Authorization头但某个接口用的Token和其他接口不一样。这时候不要在原有管理器里改来改去直接在对应HTTP请求下再加一个HTTP信息头管理器单独覆盖Authorization。这样全局配置不用动只影响这一个请求。这里有一个常见的坑如果一个请求头在父级和子级都出现了但是父级有、子级没有有些版本可能出现“合并”而不是“覆盖”。我在JMeter 5.2上实测下来同名Header确实是子级覆盖父级但为了保险起见建议在关键请求前加一个“调试取样器”或者用查看结果树确认最终发出的请求头不要凭感觉判断。2.3 验证请求头是否生效配置完成后怎么知道请求头真的发出去了最简单的方法是添加“查看结果树”监听器在界面左侧选到具体的HTTP请求样本右侧切到“请求体”或者“请求头”标签页能看到实际发送出去的报文内容。如果是压测脚本想在运行时输出请求头可以加一个JSR223取样器直接用log.info记录sample.getHttpHeaders()。还有一种比较稳妥的办法用调试取样器输出变量。虽然它直接输出的是变量值但可以帮你确认${token}这类变量有没有成功代入到请求头里属于排查问题时的辅助手段。用查看结果树配合调试取样器基本能把“没生效”和“变量没代进去”两类问题区分开。注意查看结果树里的“请求头”标签显示的是JMeter实际构建的请求头。如果你在这个标签里没看到自己配置的Header说明配置的作用域或者合并逻辑出了问题优先检查元件层级。3. 高频实战多场景请求头配置方案3.1 JSON接口与表单提交的正确姿势现在大部分后端接口都要求JSON格式。发JSON请求时的标准配置是在HTTP信息头管理器里加一行Content-Type: application/json然后HTTP请求的Body Data里填JSON字符串。有人说我填了application/json后还是报错怎么办大概率是编码问题。建议写成application/json;charsetUTF-8很多后端框架默认用UTF-8解析如果请求头里带上了charsetUTF-8基本能规避中文乱码导致的解析失败。表单提交的情况就简单一些。普通表单提交application/x-www-form-urlencoded不需要手动设置Content-TypeJMeter会默认生成。但有一种情况例外如果后端严格校验了Content-Type且不接受不带charset的默认值你可以手动加一行Content-Type: application/x-www-form-urlencoded;charsetUTF-8。注意手动设置后JMeter仍然会在请求体里按表单格式编码参数两者不冲突。3.2 认证授权Basic Auth与Bearer Token接口测试免不了遇到登录鉴权。最基础的是Basic Auth用户名密码用冒号连接后做Base64编码放到Authorization头里。JMeter中除了直接在HTTP信息头管理器里手填Authorization: Basic xxx外还可以在HTTP请求的“配置”区域直接填用户名和密码JMeter会自动生成Authorization头。手填的好处是逻辑清晰自动生成的好处是好维护我倾向于让JMeter自动生成因为它会处理Base64编码避免你手动拼错。Bearer Token更常见。Token一般由登录接口返回用JSON提取器或者正则表达式提取器取出来然后在HTTP信息头管理器里写Authorization: Bearer ${token}。这里有个容易错的点登录请求本身可能不需要Authorization但它返回的响应体里带了Token。要让后续请求使用这个Token就要把JSON提取器放在登录请求的子级并设置变量名token。后续请求一定要放在登录请求之后且HTTP信息头管理器里的Authorization值要引用这个变量名。实际项目中经常遇到Token过期要刷新、同一个线程要带不同Token的情况。这时候最稳妥的方式是每轮迭代先调用登录接口再调用业务接口。用CSV文件参数化用户名密码登录接口动态取数Token提取后会跟着线程独享天然满足并发场景。3.3 文件上传与伪装浏览器文件上传场景下不要在HTTP信息头管理器里手动填Content-Type: multipart/form-data。原因是multipart请求的Content-Type需要带一个boundary参数这个boundary由JMeter动态生成你手动填一个固定值或者干脆填错格式后端反而解析不出来。正确做法是在HTTP请求中勾选“Use multipart/form-data”然后添加文件参数即可Content-Type会自动处理。关于浏览器伪装是因为不少服务端有反爬或者反自动化策略识别到非浏览器User-Agent就拒绝响应。你可以在HTTP信息头管理器里加一行User-Agent值填浏览器实际发送的字符串比如Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36。重点关注的是版本号里的Chrome和Safari两部分很多服务端就靠这段字符串做简单识别。除了User-Agent有些服务端还会校验Accept、Referer字段这时候直接用Charles抓一次正常浏览器的请求把关键请求头原样复制到JMeter管理器里基本能解决。4. 动态请求头参数化、变量提取与脚本生成4.1 从CSV文件读取参数动态设置请求头压测和接口测试都经常用到参数化。需求大多是每个线程或者每次请求携带不同的请求头值比如不同的用户ID、不同的Token。实现方法很简单在线程组下加CSV数据文件设置配置好文件路径、变量名、分隔符然后在HTTP信息头管理器里直接引用${变量名}。这里有个容易搞混的点如果用CSV参数化了用户名但Token并不是CSV里现成的数据而是每个用户登录后动态获取的。这就涉及两种情况如果接口允许直接传用户ID这种简单的身份标识CSV参数化就够了如果后端校验的是Token需要先调登录接口拿Token再在后续请求中引用。单纯靠CSV无法解决Token动态获取必须配合提取器和后续请求。另外提醒一点CSV文件中的编码最好用UTF-8并且不要在文件末尾留空行否则可能出现最后一个变量读取为null的诡异问题排查起来非常费劲。还有一个小细节CSV数据文件设置里的“变量名称”这一栏多个变量用英文逗号分隔顺序要和CSV表头一致填反了的话整个脚本分发出来的数据就乱了。4.2 从响应中提取Token并在请求头中引用以最常见的登录后获取Token为例完整流程是这样的。先在线程组下加一个HTTP请求方法设为POST地址指向登录接口。响应体是JSON结构类似{code:0,data:{access_token:xxxx,expires_in:7200}}。在这个请求下加一个“JSON提取器”。JSON提取器里填三处关键内容要提取的JSONPath表达式比如$.data.access_token变量名比如access_token匹配数字一般填1表示取第一个匹配项。然后添加一个HTTP信息头管理器放在后续业务请求的父级管理器中加一行Authorization: Bearer ${access_token}。运行到这里时JMeter会先执行登录请求提取Token存进变量等后续请求执行到信息头管理器时自动把${access_token}替换为实际值。如果接口返回的不是JSON而是HTML或普通文本就用正则表达式提取器写一个类似access_token:([^])的正则表达式。注意转义引号和边界这是很多人容易写错的地方。推荐先用在线正则工具测好再粘进来。注意JSON提取器的“匹配数字”里填0表示随机取一个填-1表示取全部并生成变量名_1、_2这样的后缀。如果业务上只需要一个有效Token建议填1逻辑更可控。4.3 进阶JSR223动态生成签名请求头有些接口为了防止参数被篡改要求请求头带签名比如X-Sign: MD5(timestamp token 随机数)。这种动态内容没法写死在管理器里一般用JSR223预处理脚本生成。在业务请求下添加“前置处理器” - “JSR223预处理程序”语言选groovy脚本内容类似def timestamp System.currentTimeMillis().toString() def randomStr UUID.randomUUID().toString().replace(-, ) def signSource timestamp ${token} randomStr def md5 java.security.MessageDigest.getInstance(MD5).digest(signSource.getBytes(UTF-8)) def sign new BigInteger(1, md5).toString(16) while (sign.length() 32) { sign 0 sign } vars.put(timestamp, timestamp) vars.put(nonce, randomStr) vars.put(sign, sign)然后在HTTP信息头管理器里分别引用${timestamp}、${nonce}、${sign}。这里有个隐藏的雷MD5结果可能出现开头补0的情况一定要补足32位。很多业务流程不要求补零还能用要求严格的后端会直接验签失败。JSR223相比BeanShell执行性能更好从JMeter 3.0开始官方就推荐优先用JSR223。压测场景下涉及高并发验证签名的计算效率时建议用Groovy脚本并且脚本里尽量少做IO操作只做纯计算。5. 常见问题与排查技巧实录5.1 请求头相关的高频报错速查表我把自己遇到过的和同行反馈里比较典型的几类问题整理了一下可以作为排查时的参考。现象可能原因常用解决思路接口返回415 Unsupported Media TypeContent-Type没有设置成服务端要求的格式设置Content-Type: application/json;charsetUTF-8返回401 UnauthorizedAuthorization请求头缺失或Token过期、格式不对检查是否引用正确变量确认Token有效请求体中文乱码请求头没加charsetUTF-8在Content-Type里补充charsetUTF-8后端识别为爬虫拒绝访问User-Agent等标识被识别为非浏览器填写真实的浏览器User-Agent必要时补全Accept等头上传文件后后端读不到文件内容手动设置了Content-Type: multipart/form-data导致boundary异常去掉手动设置勾选Use multipart/form-data请求头里变量原样输出${token}变量未定义或作用域不对用调试取样器观察变量值检查提取器是否在正确层级每次压测第一个请求失败后面的成功Token或登录态在首个请求还没建立重新梳理控制器结构保证登录请求先执行5.2 一线排查思路从结果树到抓包遇到请求头相关的报错排错顺序很重要。先看查看结果树里的请求头是否完整。在JMeter的查看结果树里样本结果的第一个标签页是“取样器结果”里面有响应码、响应信息、请求耗时等第二个标签页显示“请求头”能直接看到实际发出去了什么。这里注意它显示的是JMeter实际构建的请求头不包含你在管理器里填了但没生效的内容。如果请求头里没有你预期的字段就得往上翻看这个头是不是加在了错误的作用域或者被其他同名请求头覆盖了。如果在结果树里请求头看起来没问题但接口还是报错就要看响应内容。用JSON提取器或者正则先把响应里的错误码字段提取出来能在日志里快速定位到具体是哪个业务分支出问题。如果后端允许抓包直接在服务器上抓一次请求和JMeter发出的请求头做对比这种方法定位最快尤其适合排查鉴权和编码问题。5.3 压测场景下请求头相关的性能与稳定性建议最后聊一个压测场景特有的话题。高并发时如果每个请求都要动态计算签名和Token脚本的计算逻辑会成为瓶颈。JSR223脚本要写高效避免在脚本里做耗时的加密操作。比如RSA加密比MD5慢很多签名算法能选择时优先选择计算速度快的算法如果业务允许可以自己生成一批预签名信息放在CSV里完全绕开实时计算。还有一点经验之谈压测时经常发现大量样本报503或连接错误但单发脚本却一切正常。这时候先不要急着怀疑请求头很可能是服务器连接池被打满或者带宽瓶颈。别把精力全放在请求头设置上要结合服务器监控指标综合判断。在稳定性方面如果Token是固定的直接在请求头里写死最简单高效。如果Token有有效期建议单独跑一个登录线程组通过属性或者文件把Token传给压测线程组而不是每个压力线程都去调登录接口。否则登录接口本身的压力会干扰被测系统的结果压测数据也不干净。个人心得JMeter设置请求头看似是“填两行键值对”的小事但很多项目中的疑难杂症都从这个不起眼的环节冒出来。我见过有人在Authorization里手打了空格还看不出来也见过因为缺少Accept头导致接口返回一堆HTML而不是JSON。调试请求头时多看结果树里实际发出的报文别只盯着自己面板里填了什么。这个习惯一旦养成能省下不少排查时间。最后再分享一个小技巧如果你需要多人协作维护JMeter脚本可以在HTTP信息头管理器里给每一行加上注释性命名比如“固定请求头-生产环境”并且把动态变量统一用大写下划线风格。这样脚本交接时下一个看图的人一眼就能分清哪些是固定值、哪些是参数化驱动的避免在请求头配置上重复踩坑。