第四章. 关联:搞定 Spring Security 认证
第四章. 关联:搞定 Spring Security 认证
Prorise第四章. 关联:搞定 Spring Security 认证
摘要:本章我们将攻克性能测试中最大的拦路虎——接口依赖。我们将模拟真实的 “登录 -> 获取 Token -> 携带 Token 访问受保护接口” 的业务闭环,掌握 JSON 提取器和正则表达式提取器的核心用法,实现跨请求的数据传递。
本章学习路径
我们将按照以下步骤构建动态的业务链路:
- 4.1 场景与靶场升级
- 4.1.1 什么是 “关联” (Correlation)
- 4.1.2 模拟 Spring Security 登录与鉴权
- 4.2 JSON 提取器实战
- 4.2.1 JSONPath 语法速成
- 4.2.2 提取 Token 变量
- 4.3 跨请求传递
- 4.3.1 HTTP 信息头管理器的使用
- 4.3.2 调试与验证变量传递
- 4.4 正则表达式提取器(进阶)
- 4.4.1 万能的 Regex 语法
- 4.4.2 提取响应头中的 Cookie
4.1. 场景与靶场升级:模拟真实的业务链
在上一章,我们通过随机参数模拟了独立的查询请求。但在现实世界中,90% 的业务操作都需要先 “登录”。
在 Spring Boot + Spring Security 的架构中,通常采用 JWT (JSON Web Token) 机制:
- 客户端调用
/login,服务端校验账号密码,返回一个加密字符串(Token)。 - 客户端在后续请求头中携带
Authorization: Bearer {Token}。 - 服务端拦截器校验 Token 有效性。
为了在 JMeter 中实现这一过程,我们需要先升级我们的 Spring Boot 靶场。
4.1.1. 编写模拟鉴权接口
为了专注于 JMeter 本身,我们不引入笨重的 Spring Security 依赖,而是手动编写代码模拟这一行为。
文件路径:src/main/java/com/demo/jmeterdemo/controller/AuthController.java
请创建新的控制器类:
1 | package com.demo.jmeterdemo.controller; |
重启项目,我们有了两个新目标:
POST /api/auth/login:获取 Token。GET /api/auth/order/create:需要 Token 才能访问。
4.2. JSON 提取器实战:抓取 Token
现在回到 JMeter。如果我们直接按顺序调用这两个接口,第二个接口必然报错(403 Forbidden),因为 JMeter 默认是一个 “健忘” 的客户端,它不会自动把上一次请求的响应带到下一次。
我们需要手动建立关联,这一步在 JMeter 中通过 后置处理器 (Post Processor) 实现。
4.2.1. 第一步:配置登录请求
创建一个新的 线程组,命名为 " S01_下单流程 "。
添加 HTTP 请求,命名为 " API_登录 "。
配置如下参数:
- Method:
POST - Path:
/api/auth/login - 消息体数据:
1 | { |
- 重要:因为我们要发送 JSON Body,必须添加 HTTP 信息头管理器 (HTTP Header Manager)。
配置步骤如下:
右键点击 " API_登录 " -> 添加 -> 配置元件 -> HTTP 信息头管理器。
添加一行:Content-Type = application/json。
4.2.2. 第二步:添加 JSON 提取器
我们的目标是从登录接口返回的 JSON 中提取 token 字段的值。
1 | { |
操作步骤:
右键点击 " API_登录 " -> 添加 -> 后置处理器 -> JSON 提取器 (JSON Extractor)。
配置核心参数:
| 参数名 | 配置值 | 解释 |
|---|---|---|
| 变量名称 (Names of created variables) | jwt_token | 给提取出来的值起个名字,后续用 ${jwt_token} 引用。 |
| JSON 路径表达式 (JSON Path expressions) | $.token | $ 代表根节点,.token 代表下一级 key。 |
| 匹配号 (Match No.) | 1 | 如果有多个 token,取第 1 个。0 代表随机,-1 代表全部。 |
| 默认值 (Default Value) | TOKEN_NOT_FOUND | 如果提取失败,变量会被赋值为这个字符串(便于排查错误)。 |
4.3. 跨请求传递:使用 Token
拿到了 Token,下一步是将其 “注入” 到下单接口的请求头中。
4.3.1. 配置下单请求
- 在线程组下添加第二个 HTTP 请求,命名为 " API_创建订单 "。
配置如下参数:
- Method:
GET - Path:
/api/auth/order/create
- 关键步骤:添加请求头。
操作步骤如下:
- 右键点击 " API_创建订单 " -> 添加 -> 配置元件 -> HTTP 信息头管理器。
- 添加一行配置:
- 名称*:
Authorization
- 名称*:
- 值*:
Bearer ${jwt_token}
- 值*:
注意:这里的值必须严格遵循后端代码的校验规则(即前缀 Bearer + 空格 + 变量)。
4.3.2. 调试与验证
点击启动运行测试,观察 察看结果树。
API_登录:响应数据中包含 Token。
API_创建订单:
验证步骤如下:
- 点击 请求 (Request) 选项卡 -> Request Headers。
- 你应该能看到
Authorization: Bearer 550e8400...。 - 如果看到
Authorization: Bearer TOKEN_NOT_FOUND,说明 JSON 提取器配置有误(通常是 JSONPath 写错了)。 - 如果响应状态码为
200且msg: "Order Created Successfully",说明关联成功!

4.4. 正则表达式提取器:处理非 JSON 场景
在现代前后端分离开发中,JSON 确实是主流。但在企业级开发中,我们经常会遇到 “老旧系统”(Legacy System)或第三方回调接口,它们返回的可能不是标准的 JSON,而是 XML、HTML 甚至纯文本字符串。此外,像 Set-Cookie、Location 重定向地址等关键信息,往往隐藏在响应头(Response Headers)而非响应体中。
面对这些场景,JSON 提取器就失效了。这时,我们需要请出 JMeter 的万能军刀——正则表达式提取器。
4.4.1. 场景升级:模拟 “老旧” 接口
为了演示这个场景,我们需要在 Spring Boot 靶场中增加一个模拟的老旧接口。它不返回 JSON,而是返回一段具有特定格式的字符串。
修改文件:src/main/java/com/demo/jmeterdemo/controller/AuthController.java
请在 AuthController 类中添加以下方法:
1 | /** |
重启项目,访问 http://localhost:8080/api/auth/legacy/status,你会看到类似这样的响应:User:admin|SessionID:sess_1731981234567|Status:Active
挑战目标:我们需要从这串文本中精准提取出 sess_1731981234567。
4.4.2. 核心语法拆解
在使用提取器之前,我们必须先搞懂正则表达式在 JMeter 中的特殊语法。
我们要提取的目标是 SessionID: 和 | 之间的内容。
正则表达式公式:SessionID:(.*?)\|
SessionID::左边界。告诉 JMeter 从哪里开始找(锚点)。():捕获组。括号里的内容就是我们真正想要的数据。.:匹配任意字符。*:匹配 0 次或多次。?:非贪婪模式(关键!)。- 如果不加
?(贪婪模式),它会一直匹配到这一行的最后一个|。 - 加上
?,它会匹配到 最近的 一个|就停止。
- 如果不加
\|:右边界。因为|在正则中是特殊字符(表示 “或”),所以需要用\转义。
4.4.3. 实战配置:提取 SessionID
现在我们来配置 JMeter 脚本。
操作步骤:
- 添加请求:在线程组下添加一个新的 HTTP 请求,命名为 " API_老旧接口 "。
- Path:
/api/auth/legacy/status
* Method:GET
添加提取器:右键点击 " API_老旧接口 " -> 添加 -> 后置处理器 -> 正则表达式提取器 (Regular Expression Extractor)。
详细配置(请严格按照下表填写):
| 参数项 | 配置值 | 深度原理解析 |
|---|---|---|
| 要检查的响应字段 | 主体 (Body) | 因为我们的数据在 Response Body 里。如果要提取 Cookie,这里需选 信息头。 |
| 引用名称 | legacy_sess | 提取后的变量名,后续用 ${legacy_sess} 使用。 |
| 正则表达式 | SessionID:(.*?)| | 见上文的语法拆解。 |
| 模板 (Template) | $1$ | $1$ 表示提取第 1 个括号对捕获的内容。如果是 $0$ 则表示提取整个表达式(包含边界)。 |
| 匹配数字 (Match No.) | 1 | 如果响应中有多个 SessionID,填 1 取第一个;填 0 会随机取一个(常用于随机点击链接)。 |
| 缺省值 | ERR_SESS | 最佳实践:永远给一个显眼的错误默认值,方便后续 Debug。 |
4.4.4. 验证与调试
提取配置好了,但正则很容易写错(比如漏了转义符)。我们如何验证它是否工作正常?
方法一:使用 Debug Sampler(推荐)
- 在线程组中添加一个 调试取样器 (Debug Sampler)(位于:添加 -> 取样器 -> Debug Sampler)。
- 这个组件的作用是把当前线程所有的变量都打印出来。
- 运行脚本。
- 在 察看结果树 中点击
Debug Sampler的响应数据。 - 搜索
legacy_sess:- ✅ 成功:
legacy_sess=sess_1731981234567 - ❌ 失败:
legacy_sess=ERR_SESS(此时需要回头检查正则表达式)
- ✅ 成功:
方法二:正则测试器(RegExp Tester)
JMeter 的 “察看结果树” 自带了一个正则测试工具,不需要反复运行脚本 即可调试。
- 点击 察看结果树,选择 " API_老旧接口 " 的请求记录。
- 将结果树面板中的下拉框(默认是 Text)切换为 RegExp Tester。
- 在
Regular expression输入框中填入SessionID:(.*?)\|。 - 点击 Test 按钮。
- 界面下方会直接显示提取结果。这是调试复杂正则最高效的方法。
4.5. 本章小结
在本章中,我们攻克了性能测试中 “数据流通” 的难题。
核心要点:
- JSON 提取器:处理标准 REST API 的首选,简单高效,认准
$.key语法。 - 正则提取器:处理非标数据(如老旧系统、HTML、Header 头信息)的终极方案。
- 口诀:
左边界(想要的内容)右边界。 - 注意:慎用贪婪模式,善用
?限制匹配范围。
- 口诀:
- 调试技巧:善用 Debug Sampler 查看变量池,或利用 RegExp Tester 实时验证正则逻辑。
下一步计划:现在我们的脚本已经能够成功登录并提取 Token 和 SessionID。但是,如果后端突然报错了(HTTP 500),或者返回了 {"code": 20001, "msg": "库存不足"},JMeter 默认还是会显示 “绿色盾牌”(因为 HTTP 状态码是 200)。这会导致我们误判测试结果。在下一章,我们将学习 断言 (Assertion),给 JMeter 装上 “火眼金睛”,让它能识别真正的业务成功。








