如何将ZAP与JMeter集成并纳入日常CI构建?含API测试需求
嘿,我来帮你梳理下ZAP和JMeter集成并纳入CI的方案,刚好你已经有现成的JMeter脚本了,这样上手会更快~
一、核心集成逻辑
咱们的核心思路是:让JMeter的所有API请求通过ZAP的代理,这样ZAP可以被动捕获每一个请求的细节;同时借助ZAP的API能力,在JMeter跑完单个API请求后,立刻触发针对该API的主动安全扫描,完全满足你「每个API按顺序执行测试」的要求。
二、本地环境配置步骤
2.1 先搞定ZAP的基础设置
- 启动ZAP工具,默认代理端口是8080(如果被占用,去
Tools -> Options -> Local Proxies里改个空闲端口就行) - 开启ZAP的API访问:进入
Tools -> Options -> API,勾选「Allow remote access」,然后记住页面顶部的API密钥(也可以自己设置一个好记的) - 配置扫描范围(上下文):可以手动把你的API域名添加到ZAP的上下文里,或者等ZAP捕获到JMeter的请求后再整理,这样能避免ZAP扫描无关地址,提升效率。
2.2 配置JMeter让请求走ZAP代理
有两种方式,选适合你的就行:
方式1:修改脚本全局配置(适合本地调试)
- 打开你的JMeter测试计划,在根节点下添加「HTTP Request Defaults」组件
- 切换到「Advanced」标签页,设置:
- Proxy Server:
localhost - Port: 填你刚才ZAP设置的代理端口(比如8080)
- Proxy Server:
- 如果你的API是HTTPS协议,得把ZAP的根证书导入JMeter的信任库:
- 在ZAP里导出证书:
Tools -> Options -> Dynamic SSL Certificates -> Save,存成zap-root-ca.cer - 用Java的
keytool命令导入到JMeter的信任库(默认路径是JMETER_HOME/bin/../lib/security/cacerts),命令如下:
(默认密码是keytool -importcert -file zap-root-ca.cer -alias zap -keystore path/to/cacerts -storepass changeitchangeit,如果改过就用你自己的)
- 在ZAP里导出证书:
方式2:命令行传参数(适合CI环境,不用改脚本)
不想动脚本的话,启动JMeter时直接加代理参数就行:
jmeter -n -t your-test-plan.jmx -Jhttp.proxyHost=localhost -Jhttp.proxyPort=8080 -Jhttps.proxyHost=localhost -Jhttps.proxyPort=8080
同样要提前把ZAP证书导入CI服务器上JMeter对应的Java信任库哦。
2.3 实现「每个API按顺序扫描」
要让JMeter和ZAP按API顺序配合,咱们可以在JMeter的每个API请求后面加个「HTTP Request」组件,调用ZAP的API触发主动扫描:
- 比如,在JMeter里的
GET /api/user请求后面,新增一个「HTTP Request」:- 请求方法选
POST - URL填
http://localhost:8080/JSON/ascan/action/scan/ - 添加参数:
apikey: 你的ZAP API密钥url: 当前要扫描的API地址(比如https://your-api-domain.com/api/user)recurse:false(只扫当前API,不递归扫子路径)
- 请求方法选
- 为了确保扫描完成后再跑下一个API,得加个等待逻辑:
可以用「JSR223 Sampler」写一段循环,调用ZAP的scanStatusAPI查询扫描进度,直到进度到100%再继续。示例代码(Groovy):def scanId = prev.getResponseDataAsString().split('"scanId":')[1].split(',')[0].trim() def status = 0 while (status < 100) { def url = "http://localhost:8080/JSON/ascan/view/scanStatus/?apikey=YOUR_ZAP_KEY&scanId=${scanId}" def response = new URL(url).getText() status = response.split('"status":')[1].split('}')[0].trim().toInteger() sleep(1000) // 每秒查一次 }
三、CI集成方案(以Jenkins为例,其他工具逻辑通用)
3.1 提前准备
- 在CI服务器上安装好ZAP和JMeter,或者直接用官方Docker镜像
owasp/zap2docker-stable(更省心) - 确保CI服务器能访问你的测试API环境和ZAP服务
3.2 流水线步骤参考
- 启动ZAP服务:
用Docker的话,命令如下:
直接安装ZAP的话,就用:docker run -d -p 8080:8080 owasp/zap2docker-stable zap.sh -daemon -port 8080 -host 0.0.0.0 -api-key YOUR_ZAP_KEYzap.sh -daemon -port 8080 -host 0.0.0.0 -api-key YOUR_ZAP_KEY - 执行JMeter脚本:
带上代理参数启动JMeter,同时触发每个API后的扫描:jmeter -n -t your-test-plan.jmx -Jhttp.proxyHost=localhost -Jhttp.proxyPort=8080 -l jmeter-result.jtl - 生成ZAP安全报告:
所有扫描完成后,调用ZAP的API生成HTML报告:curl -X GET "http://localhost:8080/HTMLreport/?apikey=YOUR_ZAP_KEY" -o zap-security-report.html - 归档报告并清理ZAP:
在CI工具里配置归档zap-security-report.html和JMeter结果文件,然后停止ZAP服务:docker stop $(docker ps -q --filter ancestor=owasp/zap2docker-stable) # 或者直接杀进程:pkill zap - 设置质量门(可选但推荐):
可以检查ZAP扫描出的高危漏洞,如果存在就让CI流水线失败,比如:
(HIGH_RISK_COUNT=$(curl -s "http://localhost:8080/JSON/alerts/view/alerts/?apikey=YOUR_ZAP_KEY&riskId=3" | grep -o '"alert":' | wc -l) if [ $HIGH_RISK_COUNT -gt 0 ]; then echo "发现高危漏洞,流水线终止" exit 1 firiskId=3对应高危,2是中危,1是低危,0是信息级)
四、常见问题排查
- JMeter请求通不过ZAP代理:检查ZAP的代理端口是否正确,有没有开启远程访问,HTTPS请求是否导入了ZAP证书。
- ZAP扫描不按顺序来:一定要确保JMeter里加了等待扫描完成的逻辑,必须等当前API扫描结束再执行下一个。
- CI里ZAP启动失败:检查CI服务器的端口是否被占用,用Docker的话确认端口映射正确。
内容的提问来源于stack exchange,提问作者Bala
相关产品推荐
相关产品推荐

