使用 mitmproxy 自定义脚本过滤请求并直接生成 JMX

news/2025/3/31 4:27:01/文章来源:https://www.cnblogs.com/zgq123456/p/18797193

下面是一个完整的解决方案,通过自定义 mitmproxy Python 脚本捕获 HTTP 流量,过滤特定请求,并直接生成 JMeter 可用的 JMX 文件,无需经过 HAR 转换中间步骤。

完整脚本代码

将以下脚本保存为 mitmproxy_jmx_exporter.py

python
复制
from mitmproxy import http, ctx
from xml.etree.ElementTree import Element, SubElement, tostring
from xml.dom import minidom
import urllib.parse
import datetimeclass JMXGenerator:def __init__(self):# 初始化JMX文档结构self.jmx = Element('jmeterTestPlan', version="1.2", properties="5.0", jmeter="5.4.1")hash_tree = SubElement(self.jmx, 'hashTree')# 创建测试计划test_plan = SubElement(hash_tree, 'TestPlan', {'guiclass': 'TestPlanGui','testclass': 'TestPlan','testname': 'Mitmproxy Generated Test','enabled': 'true'})SubElement(test_plan, 'boolProp', {'name': 'TestPlan.user_define_classpath'}).text = 'false'# 创建线程组thread_group_hash = SubElement(hash_tree, 'hashTree')self.thread_group = SubElement(thread_group_hash, 'ThreadGroup', {'guiclass': 'ThreadGroupGui','testclass': 'ThreadGroup','testname': 'Thread Group','enabled': 'true'})# 线程组配置SubElement(self.thread_group, 'intProp', {'name': 'ThreadGroup.num_threads'}).text = '1'SubElement(self.thread_group, 'intProp', {'name': 'ThreadGroup.ramp_time'}).text = '1'SubElement(self.thread_group, 'boolProp', {'name': 'ThreadGroup.scheduler'}).text = 'false'# 存储采样器的hashTreeself.samplers_hash = SubElement(thread_group_hash, 'hashTree')# 请求计数器self.request_count = 0self.filtered_count = 0def add_request(self, flow: http.HTTPFlow):"""添加HTTP请求到JMX"""url = flow.request.url# 过滤条件 - 修改这里实现你的过滤逻辑if self._should_filter(flow):self.filtered_count += 1returnself.request_count += 1# 创建HTTP采样器sampler = SubElement(self.samplers_hash, 'HTTPSamplerProxy', {'guiclass': 'HttpTestSampleGui','testclass': 'HTTPSamplerProxy','testname': f"{flow.request.method} {flow.request.host}",'enabled': 'true'})# 配置HTTP请求SubElement(sampler, 'stringProp', {'name': 'HTTPSampler.domain'}).text = flow.request.hostSubElement(sampler, 'stringProp', {'name': 'HTTPSampler.port'}).text = str(flow.request.port or 443 if flow.request.scheme == 'https' else 80)SubElement(sampler, 'stringProp', {'name': 'HTTPSampler.protocol'}).text = flow.request.schemeSubElement(sampler, 'stringProp', {'name': 'HTTPSampler.path'}).text = urllib.parse.quote(flow.request.path)SubElement(sampler, 'stringProp', {'name': 'HTTPSampler.method'}).text = flow.request.method# 添加请求头if flow.request.headers:headers = SubElement(self.samplers_hash, 'HeaderManager', {'guiclass': 'HeaderPanel','testclass': 'HeaderManager','testname': 'HTTP Header Manager','enabled': 'true'})collection_prop = SubElement(headers, 'collectionProp', {'name': 'HeaderManager.headers'})for name, value in flow.request.headers.items():if name.lower() in ['host', 'content-length']:  # 跳过这些头continueelement_prop = SubElement(collection_prop, 'elementProp', {'name': name,'elementType': 'Header'})SubElement(element_prop, 'stringProp', {'name': 'Header.name'}).text = nameSubElement(element_prop, 'stringProp', {'name': 'Header.value'}).text = valueSubElement(self.samplers_hash, 'hashTree')# 添加请求体if flow.request.content:SubElement(sampler, 'boolProp', {'name': 'HTTPSampler.postBodyRaw'}).text = 'true'SubElement(sampler, 'elementProp', {'name': 'HTTPsampler.Arguments','elementType': 'Arguments'})SubElement(sampler, 'stringProp', {'name': 'Argument.value'}).text = flow.request.content.decode('utf-8', errors='replace')SubElement(self.samplers_hash, 'hashTree')def _should_filter(self, flow: http.HTTPFlow) -> bool:"""定义过滤逻辑"""# 示例1: 排除静态资源if flow.request.path.endswith(('.js', '.css', '.png', '.jpg', '.gif', '.ico', '.woff', '.woff2')):return True# 示例2: 排除特定域名excluded_domains = ['google-analytics.com', 'googletagmanager.com']if any(domain in flow.request.host for domain in excluded_domains):return True# 示例3: 只包含特定API路径# if not flow.request.path.startswith('/api/'):#     return Truereturn Falsedef save_jmx(self, filename: str):"""保存JMX文件"""xml_str = tostring(self.jmx, encoding='utf-8')pretty_xml = minidom.parseString(xml_str).toprettyxml(indent="  ", encoding='utf-8')with open(filename, 'wb') as f:f.write(pretty_xml)ctx.log.info(f"Saved JMX file with {self.request_count} requests (filtered {self.filtered_count} requests)")# 全局JMX生成器实例
jmx_generator = JMXGenerator()def request(flow: http.HTTPFlow):"""处理每个请求"""jmx_generator.add_request(flow)def done():"""mitmproxy结束时保存JMX文件"""jmx_generator.save_jmx('mitmproxy_generated.jmx')# 启动命令: mitmproxy -s mitmproxy_jmx_exporter.py

使用说明

  1. 安装依赖

    bash
    复制
    pip install mitmproxy xmltodict
  2. 运行脚本

    bash
    复制
    mitmproxy -s mitmproxy_jmx_exporter.py

    或使用非交互模式:

    bash
    复制
    mitmdump -s mitmproxy_jmx_exporter.py
  3. 配置代理

    • 设置设备或浏览器使用 mitmproxy 作为代理(默认端口 8080)

    • 安装 mitmproxy 的 CA 证书以捕获 HTTPS 流量

自定义过滤规则

修改脚本中的 _should_filter 方法实现你的过滤逻辑:

python
复制
def _should_filter(self, flow: http.HTTPFlow) -> bool:"""自定义过滤逻辑"""# 示例: 只记录特定API路径if not flow.request.path.startswith('/api/v1/'):return True# 示例: 排除OPTIONS方法if flow.request.method == 'OPTIONS':return True# 示例: 只包含特定内容类型content_type = flow.request.headers.get('Content-Type', '')if 'application/json' not in content_type:return Truereturn False

生成的 JMX 文件包含

  1. 完整的测试计划结构

  2. 线程组配置

  3. 每个 HTTP 请求采样器

  4. 请求方法、URL、头信息

  5. 请求体内容

  6. 自动过滤掉的静态资源和不需要的请求

高级功能扩展

  1. 添加思考时间

    python
    复制
    # 在add_request方法中添加
    if self.request_count > 0:timer = SubElement(self.samplers_hash, 'ConstantTimer', {'guiclass': 'ConstantTimerGui','testclass': 'ConstantTimer','testname': 'Think Time','enabled': 'true'})SubElement(timer, 'stringProp', {'name': 'ConstantTimer.delay'}).text = '1000'  # 1秒SubElement(self.samplers_hash, 'hashTree')
  2. 自动参数化

    python
    复制
    # 自动替换session ID等为变量
    if 'session_id' in flow.request.path:flow.request.path = flow.request.path.replace(session_id, '${SESSION_ID}')
  3. 添加断言

    python
    复制
    # 在add_request方法末尾添加
    assertion = SubElement(self.samplers_hash, 'ResponseAssertion', {'guiclass': 'AssertionGui','testclass': 'ResponseAssertion','testname': 'Response Assertion','enabled': 'true'
    })
    SubElement(assertion, 'stringProp', {'name': 'Assertion.test_field'}).text = 'Assertion.response_code'
    SubElement(assertion, 'intProp', {'name': 'Assertion.test_type'}).text = '2'  # 2表示相等
    SubElement(assertion, 'stringProp', {'name': 'Assertion.test_string'}).text = '200'

这个脚本提供了高度可定制的解决方案,可以直接从实时流量生成准备就绪的 JMeter 测试计划,特别适合复杂 API 的测试场景创建。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go红队开发—CLI框架(二)

Go红队开发—CLI命令行工具编写基础学习(二)。目录CLI开发框架cobra 集成库目录规范搭建框架根命令参数添加子命令帮助信息爬虫功能(趁热打铁)Goquery处理响应编码处理收集百度热搜榜爬虫功能所有源码 CLI开发框架 师傅们久等了,为了加快进度,这章节添加了一个爬虫功能,也是…

APP性能测试工具-GT

GT(随身调)是腾讯研发的一款可以用来做App性能测试的工具,可以对APP进行快速的性能测试,检测App的CPU、内存、流量、电量、帧率/流畅度等等、还能开启日志的查看、Crash日志查看、网络数据包的抓取、APP内部参数的调试、真机代码耗时统计等。 虽然现在该项目已经停止维护了…

一文速通Python并行计算:04 Python多线程编程-多线程同步(上)—基于条件变量、事件和屏障

本文介绍了Python多线程同步的三种机制:条件变量(Condition)、事件(Event)和屏障(Barrier),条件变量指的是线程等待特定条件满足后执行,适用于生产者-消费者模型;Event指的是线程通过事件标志进行同步,适用于线程间简单通信;Barrier指的是多个线程需同步到同一阶段…

docker desktop windows安装

我的机器windows 11 家庭版 下载docker desktop for windows 就直接安装了。安装后打开,遇到了界面转圈圈加载不出来问题,docker engine也是stopped. 病急乱投医,先是说要启用hyper-v,控制面板=》程序和功能里没有发现有hyper-v,一看是家庭版,网上倒是有一个脚本可以在家…

C语言打卡学习第6天(2025.3.25)(补发)

只做了一些有关循环分支函数求值的题,感觉循环函数其实差不多,只有一些细微差别,可能是做的题还不够多或者看运用场景吧

C语言打卡学习第5天(2025.3.24)(补发)

1、把char,getchar,putchar简单看了一下,求ascii值之类的 之类的简单看了一下 2、交换值那一题很奇怪,结果我输出的跟答案要求是一样的,交过去之后显示答案错误,白天的时候问一下

Vulnstack红日靶场通关(持续更新)

带你速通内网渗透相关知识点!!!Vulnstack通关 来源于《内网渗透实战攻略》实战部分 个人是写下自己的笔记 攻击链:探索发现阶段->入侵和感染阶段->攻击和利用阶段->探索感知阶段->传播阶段->持久化和恢复阶段 Windows权限级别前置知识:权限层级 账户类型 权…

Ubuntu 24.04安装MySQL,并且配置外网访问

安装启动更新软件包列表sudo apt update安装MySQL软件包sudo apt install mysql-server启动MySQL服务sudo systemctl start mysql重启命令:systemctl restart mysql配置外网访问 需要修改一个配置 vim /etc/mysql/mysql.conf.d/mysqld.cnf注释掉 这行 配置 bind-address …

2022CCPC Online Contest G - Name the Puppy

对正串和反串分别建立 Trie 树,定义 \(dp[i][j]\) 表示正串 Trie 树上编号为 \(i\) 的点匹配反串 Trie 树上编号为 \(j\) 的点所能拼出最长 anti-border 的长度。 如此,从根节点开始搜索,直到无法匹配为止都可以搜,搜到底后回到根节点继续匹配,可以证明,拼出来的 anti-bo…

互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp智能体框架开发语音交互

前言 前段时间太忙了博客一直都没来得及更新,但是不代表我已经停止开发了,刚好最近把语音部分给调整了一下,所以就来分享一下具体的内容了。我想说一下,更新晚还是有好处的,社区已经有很多的小伙伴自己实现了一些语音对话功能的案例,比如小智也有.NET客户端了,还有就是一…

【AI News | 20250327】每日AI进展

AI Repos 1、playwright-mcp 使用Playwright提供浏览器自动化功能的MCP服务,核心是让LLM通过结构化的可访问性快照与网页交互,不需要依赖截图或视觉模型。可以用来自动填写网页表单、自动收集网页信息、自动进行网页测试等。支持两种模式:快照模式(默认):使用可访问性快照…

markdown常用命令行格式

Markdown 主要命令(语法)如下:标题 使用 # 号表示标题,# 的个数决定标题的级别:一级标题 二级标题 三级标题 四级标题 五级标题 六级标题段落 & 换行 直接输入文字形成段落,使用两个以上空格或 进行换行:这是一个段落。 这是同一段的下一行。 使用 <br> 也可…