通知渠道
使用通知渠道来获取关于不同 Defender 模块的事件通知,比如 Monitor 触发器,工作流或者 Relayer 交易生命周期事件。
附加配置
Webhook 密钥
作为一项额外的安全措施,Defender 实现了基于哈希的消息认证码 (HMAC),通过添加 Defender-Signature
和 Defender-Timestamp
请求头到发送到 webhook 端点的通知中。因此,接收通知的端点可以验证请求的真实性。
每个 webhook 通知都有一个与之关联的密钥,可以在 Settings → Notification Channnels → Webhook details 下访问。
Defender-Signature
使用 SHA256 algorithm 和 webhook secret
来签名 payload 和时间戳。
只有账户中的管理员用户才有权限查看 webhook 密钥。 |
签名验证
使用 Defender SDK
签名的真实性可以使用 Defender SDK 中的 verifySignature
实用函数来验证。
function webhookHandler(req, res) {
const signature = req.headers['Defender-Signature'];
const timestamp = req.headers['Defender-Timestamp'];
const defender = new Defender({
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
});
const result = client.notificationChannel.verifySignature({
body: req.body,
signature,
timestamp,
secret: process.env.WEBHOOK_SECRET,
validityInMs: 1000 * 60 * 10, // 10 mins
});
if (!result.valid) throw new Error(result.error);
// your handler code
}
Python 示例
该代码示例在 Python 3.12 中测试。对于不同的版本,代码可能略有不同。 |
from datetime import datetime, timedelta, UTC
import hmac
import hashlib
def verify_signature(body_object: dict, timestamp: str, signature: str secret: str) -> bool:
# Parse the timestamp
try:
timestamp_dt = datetime.fromisoformat(timestamp)
except ValueError:
return False # Invalid timestamp format
# Get the current time and calculate the time difference
current_time = datetime.now(UTC)
time_difference = current_time - timestamp_dt
# Check if the time difference is within the allowed range (10 minutes)
if time_difference > timedelta(minutes=10):
return False
# Merge timestamp with body_object
payload_to_verify = {**body_object, 'timestamp': timestamp}
payload_to_verify_str = json.dumps(payload_to_verify, separators=(',', ':'))
# Create a new HMAC object using the secret and the SHA256 hash algorithm
hmac_obj = hmac.new(secret.encode(), payload_to_verify_str.encode(), hashlib.sha256)
# Generate signature
generated_signature = hmac_obj.hexdigest()
# Compare the generated signature with the provided signature
return hmac.compare_digest(generated_signature, signature)