密钥
签名验证
X-Firecrawl-Signature 的请求头:
如何验证
- 从
X-Firecrawl-Signature头中提取签名 - 获取原始请求体(不要先解析)
- 使用你的密钥计算 HMAC-SHA256
- 使用时间安全的比较函数比较签名
实现
最佳实践
始终验证签名
使用时间常数/计时安全的比较
crypto.timingSafeEqual(),在 Python 中使用 hmac.compare_digest()。
Documentation Index
Fetch the complete documentation index at: /llms.txt
Use this file to discover all available pages before exploring further.
验证 Webhook 的真实性
X-Firecrawl-Signature 的请求头:
X-Firecrawl-Signature: sha256=abc123def456...
X-Firecrawl-Signature 头中提取签名import crypto from 'crypto';
import express from 'express';
const app = express();
// 使用原始请求体解析器进行签名校验
app.use('/webhook/firecrawl', express.raw({ type: 'application/json' }));
app.post('/webhook/firecrawl', (req, res) => {
const signature = req.get('X-Firecrawl-Signature');
const webhookSecret = process.env.FIRECRAWL_WEBHOOK_SECRET;
if (!signature || !webhookSecret) {
return res.status(401).send('未授权');
}
// 从签名头中提取哈希值
const [algorithm, hash] = signature.split('=');
if (algorithm !== 'sha256') {
return res.status(401).send('签名算法无效');
}
// 计算期望的签名
const expectedSignature = crypto
.createHmac('sha256', webhookSecret)
.update(req.body)
.digest('hex');
// 使用恒定时间比较进行签名校验
if (!crypto.timingSafeEqual(Buffer.from(hash, 'hex'), Buffer.from(expectedSignature, 'hex'))) {
return res.status(401).send('签名无效');
}
// 解析并处理已校验的 webhook
const event = JSON.parse(req.body);
console.log('已校验的 Firecrawl webhook:', event);
res.status(200).send('ok');
});
app.listen(3000, () => console.log('监听端口 3000'));
import hmac
import hashlib
from flask import Flask, request, abort
app = Flask(__name__)
WEBHOOK_SECRET = 'your-webhook-secret-here' # 从 Firecrawl 控制台获取
@app.post('/webhook/firecrawl')
def webhook():
signature = request.headers.get('X-Firecrawl-Signature')
if not signature:
abort(401, '缺少签名请求头')
# 从签名请求头中提取哈希值
try:
algorithm, hash_value = signature.split('=', 1)
if algorithm != 'sha256':
abort(401, '签名算法无效')
except ValueError:
abort(401, '签名格式无效')
# 计算期望的签名
expected_signature = hmac.new(
WEBHOOK_SECRET.encode('utf-8'),
request.data,
hashlib.sha256
).hexdigest()
# 使用计时安全的比较验证签名
if not hmac.compare_digest(hash_value, expected_signature):
abort(401, '签名无效')
# 解析并处理已验证的 webhook
event = request.get_json(force=True)
print('已验证的 Firecrawl Webhook:', event)
return 'ok', 200
if __name__ == '__main__':
app.run(port=3000)
app.post('/webhook', (req, res) => {
if (!verifySignature(req)) {
return res.status(401).send('未授权');
}
processWebhook(req.body);
res.status(200).send('OK');
});
crypto.timingSafeEqual(),在 Python 中使用 hmac.compare_digest()。
