外部事件注入与 Webhook 集成
外部事件注入与 Webhook 集成
学习目标
读完本章后,你将能够:
- 设计安全的 Webhook 端点将外部事件注入 Agent 网络
- 实现基于签名令牌的轻量级认证机制
- 处理多种 HTTP 方法和内容类型的请求路由
- 理解 Webhook Agent 与直接端点的权衡
核心概念
为什么需要外部事件注入
Agent 网络内部的 Event 传播是自洽的,但需要从外部世界接收事件才能与现实世界交互。
两种注入方式
| 方式 | 机制 | 适用场景 |
|---|---|---|
| 直接端点 | HTTP 请求直接路由到特定 Agent | 简单集成、一对一映射 |
| Webhook Agent | Agent 主动轮询外部 API | 无 Webhook 支持的系统、需要认证 |
直接端点架构
路由设计
/users/:user_id/web_requests/:agent_id/:secret三层定位确保精确路由:
请求处理约定
Agent 的 receive_web_request 方法返回格式统一的响应:
# 返回值: [response_body, status_code, content_type?, headers?]def receive_web_request(params, method, format) # 验证 secret return ["unauthorized", 401] unless params[:secret] == options[:secret]
# 处理请求 create_event(payload: params) [{ status: "ok" }, 200]end| 返回格式 | 含义 |
|---|---|
["response", 200] | 纯文本响应 |
[{ json: "data" }, 200] | JSON 响应 |
["redirect_url", 302] | 重定向 |
["xml", 200, "text/xml", {"Access-Control-Allow-Origin" => "*"}] | 带自定义头和 MIME 的响应 |
安全设计
三层安全机制
| 层级 | 机制 | 防御目标 |
|---|---|---|
| URL 结构 | user_id 限定用户范围 | 跨用户访问 |
| Agent 归属 | user.agents.find_by_id | 用户间 Agent 隔离 |
| Secret 令牌 | Agent 内部验证 params[:secret] | 未授权访问 |
安全最佳实践
# Agent 内部验证 secretdef receive_web_request(params, method, format) return ["invalid secret", 403] if params[:secret] != options[:expected_secret] # ... 处理逻辑end重要:Secret 验证应在 Agent 内部完成,而非依赖路由层——因为路由层已经验证了用户和 Agent 归属,Secret 是额外的应用层认证。
设计模式
模式一:事件网关
一个 Agent 作为统一的 Webhook 入口,根据请求内容分发给不同下游:
模式二:双向交互
Agent 既接收 Webhook 请求,又返回响应:
陷阱与对策
陷阱一:CSRF 攻击
Webhook 端点跳过 CSRF 验证,可能被恶意页面利用。
对策:Webhook 端点使用 skip_before_action :verify_authenticity_token,但依赖 Secret 令牌认证。GET 请求无副作用,POST 请求必须验证 Secret。
陷阱二:重放攻击
攻击者捕获合法 Webhook 请求并重复发送。
对策:
- 在 Event payload 中记录时间戳,下游 Agent 过滤过期事件
- 使用 DeDuplicationAgent 去重
- 对于支付类场景,验证外部系统的签名(如 Stripe 签名头)
陷阱三:请求洪水
恶意请求导致 Agent 创建大量无效 Event。
对策:
- Agent 的
expected_receive_period_in_days配合working?方法检测异常频率 - 使用 TriggerAgent 过滤无效 payload
- 外部限流(Nginx rate limiting)
设计取舍
直接端点 vs Webhook Agent
| 维度 | 直接端点 | Webhook Agent |
|---|---|---|
| 延迟 | 即时(请求即处理) | 延迟(轮询间隔) |
| 外部要求 | 需要外部系统主动推送 | 无需外部配合 |
| 认证 | Secret 令牌 | API Key/OAuth |
| 可靠性 | 依赖外部推送可靠性 | 自主控制轮询频率 |
| 适用场景 | GitHub/Stripe 等标准 Webhook | 无 Webhook 的传统 API |
URL 路由 vs 统一端点 + 内容分发
| 维度 | URL 路由(每个 Agent 一个 URL) | 统一端点 + 内容分发 |
|---|---|---|
| 配置复杂度 | 低(URL 即路由) | 高(需解析内容) |
| 安全性 | 每个 URL 独立 Secret | 统一认证层 |
| 灵活性 | 一对一映射 | 一对多分发 |
| 调试 | 简单(URL 对应 Agent) | 复杂(需追踪分发逻辑) |
参考来源
- Webhooks.org — Webhook 技术标准与最佳实践
- RFC 7231 — HTTP/1.1 语义与内容协商