如何使用OWASP ZAP自动生成API请求头签名?
我刚好处理过类似的API签名校验场景,用OWASP ZAP来实现完全没问题——核心是利用ZAP的脚本扩展(支持Javascript、Python等),在请求发送前拦截请求、计算签名并自动注入到Signature请求头中。下面是具体的实现步骤和示例,帮你快速搞定:
核心思路
ZAP的Http Sender脚本类型允许我们在请求被发送到目标服务器前,对请求内容进行自定义修改。我们要做的就是:
- 拦截目标POST请求
- 解析请求体中的指定字段,按规则拼接字符串
- 用共享密钥对拼接后的字符串进行哈希运算生成签名
- 将签名、API-Key及其他必要头信息添加到请求中
具体实现(以Javascript脚本为例)
Javascript是ZAP默认支持的脚本语言,上手成本低,适合快速验证:
步骤1:创建Http Sender脚本
- 打开ZAP,点击顶部菜单的 Tools > Scripts
- 在Scripts窗口中,右键点击 Http Sender 文件夹,选择 New Script
- 选择脚本类型为 JavaScript,命名为
GenerateSignature.js,点击OK
步骤2:编写脚本逻辑
将以下代码粘贴到脚本编辑器中,根据你的API实际情况修改配置参数和字段列表:
// 配置参数 - 建议用ZAP环境变量替代硬编码(更安全) const SHARED_SECRET = "your_shared_secret_here"; const API_KEY = "your_api_key_here"; const HASH_ALGORITHM = "SHA-256"; // 匹配后端用的哈希算法,比如SHA-1、MD5等 function sendingRequest(msg, initiator, helper) { // 只处理目标POST请求,可添加URL过滤逻辑 if (msg.getMethod() !== "POST") { return; } // 解析JSON请求体 let requestBody = msg.getRequestBody().toString(); let bodyJson; try { bodyJson = JSON.parse(requestBody); } catch (e) { print("Failed to parse request body as JSON: " + e); return; } // 提取需要签名的字段(顺序必须和后端校验逻辑完全一致!) const fieldsToSign = [bodyJson.field_one, bodyJson.field_two]; // 拼接字段字符串 const signString = fieldsToSign.join(""); // 用ZAP内置工具计算哈希签名 const signature = helper.hash(signString, SHARED_SECRET, HASH_ALGORITHM); // 设置请求头 msg.getRequestHeader().setHeader("API-Key", API_KEY); msg.getRequestHeader().setHeader("Signature", signature); msg.getRequestHeader().setHeader("Content-Type", "application/json"); msg.getRequestHeader().setHeader("Accept", "application/json"); // 必须调用此方法保存修改 msg.setRequestBody(requestBody); } function responseReceived(msg, initiator, helper) { // 响应阶段无需处理,留空即可 }
步骤3:启用脚本
- 在Scripts窗口中找到
GenerateSignature.js,右键点击选择 Enable - 如果有多个Http Sender脚本,可调整优先级确保此脚本先执行
关键注意事项
- 字段顺序绝对不能错:后端拼接字段的顺序如果和脚本里的不一致,签名肯定会校验失败,这是最容易踩坑的点
- 哈希算法要完全匹配:确认后端使用的哈希算法,脚本里的
HASH_ALGORITHM必须对应 - 安全存储密钥:不要把共享密钥和API-Key硬编码在脚本里,建议用ZAP的 Environment Variables(路径:Tools > Options > Environment Variables)设置,然后用
java.lang.System.getenv("VAR_NAME")读取 - 非JSON请求体处理:如果你的API用form-data或其他格式,需要调整请求体解析逻辑,比如用
helper.parseFormData(requestBody)来处理表单数据
可选:Python脚本实现
如果更熟悉Python,也可以用Python脚本实现,逻辑和Javascript一致:
import json # 配置参数 SHARED_SECRET = "your_shared_secret_here" API_KEY = "your_api_key_here" HASH_ALGORITHM = "SHA-256" def sending_request(msg, initiator, helper): if msg.getMethod() != "POST": return request_body = msg.getRequestBody().toString() try: body_json = json.loads(request_body) except Exception as e: print(f"Failed to parse request body: {str(e)}") return # 拼接需要签名的字段(顺序与后端一致) sign_string = f"{body_json['field_one']}{body_json['field_two']}" # 计算哈希签名 signature = helper.hash(sign_string, SHARED_SECRET, HASH_ALGORITHM) # 设置请求头 msg.getRequestHeader().setHeader("API-Key", API_KEY) msg.getRequestHeader().setHeader("Signature", signature) msg.getRequestHeader().setHeader("Content-Type", "application/json") msg.getRequestHeader().setHeader("Accept", "application/json") msg.setRequestBody(request_body) def response_received(msg, initiator, helper): pass
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

