Zenova 文档

27. 网关扩展与开放 API

完整版章节。内容按 2026.10 主线代码核对;具体入口以当前许可、账号权限和交付环境为准。

返回概览 · 完整版目录 · 下载完整 PDF

本章内容:本章面向租户管理员、系统管理员、安全管理员与集成开发人员,说明三类扩展方式:在网关请求处理链路中运行的网关扩展插件(用于企业自有的准入、改写与合规标识,支持热更新与版本回切)、流量规则中不写代码的请求与响应改写,以及用访问密钥签名调用平台管理接口的开放 API。本章同时说明网关在访问域名、来源网段控制与跨租户隔离上的边界能力。读完后,你可以开发并上线一个网关插件、在不改业务代码的前提下调整请求与响应、用脚本或自建智能体调用平台接口。

本章的「插件」指「管理后台 › 流量 › 网关扩展」中的网关插件,不是「管理后台 › 能力 › 插件」中供智能体使用的插件(第 23 章)。

27.1 网关扩展目录与插件详情

适用场景:查看平台内置与本租户上传的网关插件,了解它们的状态、版本与绑定范围。

前提:租户管理员或系统管理员权限。

操作步骤:进入「管理后台 › 流量 › 网关扩展」。目录列出平台内置插件与本租户上传的私有插件,列包括「插件」「类型与能力」「当前版本」「状态」「绑定数」「凭据绑定数」「最近更新」,右上角为「下载 SDK」「上传插件」。

图 27-1 网关扩展目录:内置与自定义插件同列展示,显示类型、版本、状态、绑定数与最近更新

你会看到

  • 状态有「未安装」「已安装」「已生效」「已停用」四种。
  • 点「管理」进入插件详情,页签依次为:
  • 「概览」:扩展 ID、可见范围、安装与运行状态、当前版本与供应链标识;
  • 「配置」:按插件声明的表单填写并保存;
  • 「版本」:版本历史与产物摘要;
  • 「绑定」:流量绑定与凭据绑定;
  • 「权限」:插件声明的网络目标、密钥要求与数据要求;
  • 「执行统计」:执行次数、按结论与按钩子的计数、执行记录。
图 27-2 插件详情概览:身份信息、可见范围「本租户」、安装与运行状态、当前版本与供应链标识

注意:安装、启用与卸载都记入「管理后台 › 审计与合规 › 操作审计」。上传私有插件前,先在「权限」页签核对其声明的网络目标是否符合本单位要求。

27.2 下载 SDK 与开发插件

适用场景:企业需要在网关上运行自有逻辑,例如按内部规则准入、给请求补充身份头、调用自研审核服务。

操作步骤

  1. 填写「插件标识」(1~128 个字母、数字、点、下划线或短横线),点「下载 SDK」。
  2. 需要让编程助手按本网关的接口编写插件时,点「下载开发说明」获取 SKILL.md;SDK 包中也附带一份。
图 27-3 下载网关扩展 SDK:选择开发语言、填写插件标识,可单独下载给编程助手的开发说明

你会看到:SDK 包内含 manifest.json(清单版本、宿主接口版本、钩子、服务类型与失败策略)、plugin.lua(示例逻辑)、harness.lua(本地自检)、.zr/sdk/(类型标注与本地模拟宿主)与 README。两种语言使用相同的安全限制。

构建与校验:用 zr-plugin build . --output ./dist/plugin.zip 生成插件包,再用 zr-plugin validate ./dist/plugin.zip 校验。validate 与服务端上传使用同一套校验,会在生产宿主中实际编译、执行一次合成请求。

运行限制

项目限制
:--:--
指令预算每次执行 2,000,000
单次执行时长20 毫秒
内存4 MiB
插件包大小不超过 140 MiB
外部 HTTP 请求只能访问清单中声明、并由凭据绑定授权的目标
钩子请求头、请求体、响应头、响应流、响应整包、响应结束,共 6 个

超出限制即中断执行,按失败策略处理:「失败关闭」(插件超时或出错时拒绝请求)或「失败放行」。安全相关插件应使用「失败关闭」。

注意:「下载 SDK」拿到的模板不能直接上传——插件包里必须是 manifest.json 加编译好的组件,请按 README 用 zr-plugin build 生成;把源码直接打成压缩包上传会被判为「插件包内容有问题」。

27.3 上传、安装与绑定

操作步骤

  1. 在目录中点「上传插件」,选中构建好的插件包。平台校验包结构、清单、制品摘要、接口版本与配置结构,通过后提示「插件已发布」。
  2. 对插件点「安装」,或打开详情在「配置」页签操作;安装前先看「权限」页签声明的网络目标与密钥要求。
  3. 填写配置后安装;无需配置的插件点「以空配置安装(停用)」。插件以停用状态安装,状态变为「已安装」。
  4. 在「绑定」页签点「创建绑定」,填写服务类型、作用范围(「全部服务」或「指定服务」)、调用方(可选,留空表示不限制)、配置覆盖(JSON,留空 {} 表示使用安装时的默认配置),再在弹窗内点「创建绑定」。
  5. 打开右上角的「启用」开关,等状态变为「已生效」。
  6. 用命中与不命中绑定范围的请求分别核对,再到「执行统计」中查看。
图 27-4 创建绑定:服务类型、全部或指定服务、可选调用方与配置覆盖

你会看到:命中绑定范围的请求按插件逻辑处理,例如响应头中出现插件写入的标记;不命中的请求不受影响。「执行统计」中对应钩子的执行次数增加;在「管理后台 › 观测中心 › 运行总览 › 请求」打开该次调用,还能看到插件的执行记录。

图 27-5 执行统计:执行次数与按结论、按钩子的计数,执行记录逐条列出钩子、结论、耗时与绑定

注意

  • 插件已停用时绑定不生效,「绑定」页签提示「插件已停用,绑定暂不生效」。
  • 指定服务的绑定优先于同一插件的「全部服务」绑定;同一次请求每个钩子只执行一次。
  • 页面上有两个都叫「创建绑定」的按钮(页签顶部一个、绑定弹窗内一个),要在弹窗内确认后才真正提交。
  • 也可以在流量规则中添加处置动作「挂载插件」,让插件只对命中该规则的请求执行;流量规则只能进一步缩小已绑定的范围。
  • 插件需要访问外部服务时,在「绑定」的凭据绑定中以逻辑名称引用密钥,并限定允许的目标地址。

校验不通过时的提示:不是合法的插件包时提示「插件包内容有问题,请修复后重新上传」;宿主接口版本过旧时提示用新版本 SDK 重新构建;清单不符合规范时整个插件被拒收。上传成功后,插件作为本租户私有插件出现在目录中,状态为「未安装」,可见范围为「本租户」。每次上传(包括被拒收的)都记入操作审计。

27.4 升级、回切与停用

操作步骤

  1. 打开插件详情的「版本」页签,在「插件版本管理」中点「上传新版本」提交完整插件包,或对已有版本点「切换到此版本」。
  2. 在「目标版本配置」中核对后点「继续预览」。预览会列出将被删除的配置键,需要勾选确认。
  3. 在「确认插件变更」中核对影响后点「确认」。页面显示逐副本的发布进度,完成后所有网关副本均运行新版本。
图 27-6 版本页签:当前版本、源版本、渠道与供应链标识,历史版本保留产物与 SHA-256

注意:旧版本的产物与 SHA-256 保留在版本历史中,可以随时切回;新版本在网关运行失败时,平台自动回滚并提示「自动回滚完成」。升级时移除仍有绑定的服务类型会被拒绝,需要先删除对应绑定。升级后先在试点服务上核对流式与非流式输出,再扩大绑定范围。

停用与卸载:关闭详情右上角的「启用」开关后,插件不再执行,绑定保留,再次启用即恢复。点「卸载」时,确认框会列出将清理的绑定、配置、凭据绑定与引用该插件的流量规则;本租户私有插件可以同时勾选「同时删除这个租户私有插件包及全部版本」。卸载前建议先停用并观察业务调用。

27.5 请求与响应改写

适用场景:不开发插件,就在网关上统一补充或删除请求头、调整请求字段、精简返回给调用方的响应,或把上游的某个状态码换成调用方能理解的状态码。

前提:许可中包含「动态路由」或「模型护栏」模块;规则的条件已能准确限定调用方、模型或路径。

操作步骤

  1. 在「管理后台 › 流量 › 流量规则」新建或编辑规则,设置匹配条件。
  2. 点「添加处置动作」,选「改写请求」或「改写响应」,按需添加下列改写项:
动作改写项可做的操作
:--:--:--
改写请求请求头「设为」「追加」「删除」
改写请求请求参数变换用 JSON Pointer 指定字段(如 /messages/0/content),「新增」「覆盖」「删除」
改写请求请求体修改在请求体里「复制」「搬移」字段,或把字段转成另一种类型
改写响应响应头「设为」「追加」「删除」
改写响应响应体格式化「只保留列出的字段」等,对非流式的最终响应生效
改写响应状态码修改填写「上游状态码」与要「换成」的状态码
  1. 在「改写失败处理」中选择失败时的处置:模型调用在「模型入口改写失败时」选择拒绝请求或保留原始内容继续处理;MCP、A2A 与 API 服务在「能力入口改写失败时」选择阻断调用或保留原内容继续调用。请求头、响应头与状态码改写失败时只能拒绝本次调用。
  2. 保存规则,在「确认变更」中核对后点「确认并应用」。

你会看到

  • 命中规则的请求只修改指定字段,未命中的请求保持原样。
  • 在「运行总览 › 请求」打开调用详情,「路由与改写」中显示命中的规则与改写结果。
  • 改写敏感请求头时,该行标注「敏感头 · 保存需二次确认」,保存时需要勾选确认。

注意:响应体格式化发生在最终响应确定之后,不作用于流式增量片段;业务需要流式返回时,不要依赖它修改输出。不要把上游的失败包装成成功响应,也不要改写模型、计费归属等受治理的字段。需要引用密钥的请求头,请使用插件的凭据绑定(27.3 节),不要把密钥原文写进规则。改写响应契约后,同步通知调用方。

27.6 用内置策略实现请求拦截与并发上限

适用场景:拦截某类请求、限制同时执行的请求数——不需要开发插件,直接作为流量规则的处置动作。

前提:许可中包含「动态路由」或「模型护栏」模块。

操作步骤

  1. 在「流量规则」中点「新建规则」,在「条件判断」中添加条件把规则收窄到目标流量,如「调用类型」为模型调用、「模型」为指定模型,再加一个专用请求头。
  2. 点「添加处置动作」:请求拦截选「拒绝本次调用」并填写原因码;并发上限选「应用限额」,开启「并发」并填写上限与计数维度。
  3. 「配置检查」显示正常后点「保存规则」,在「确认变更」中核对字段差异与命中顺序,点「确认并应用」。
图 27-7 请求拦截规则:条件收窄到指定模型与专用请求头,动作为「拒绝本次调用」

你会看到

  • 命中拦截规则的请求返回 403 permission_denied,deniedBy 为 routePolicy,details 中带配置的原因码,不调用上游;不命中的请求正常返回。该请求在「运行总览 › 请求」中状态为「已拦截」。
  • 并发上限为 N 时,同时进行的请求不超过 N 个,超出部分返回 429 TRAFFIC_CONCURRENCY_LIMITED 并带 Retry-After,请求结束后释放名额。

注意:规则按清单顺序评估,排在前面、条件更宽且结束匹配的规则会让后面的规则无法命中,保存前在「确认变更」中核对命中顺序。规则与限额的完整说明见第 26 章。

27.7 为模型回答添加 AI 生成内容标识

内置插件「AI 生成内容标识」按《人工智能生成合成内容标识办法》与 GB 45438-2025,为模型回答添加显式文字标识,并在响应头写入隐式标识元数据。配置字段与操作步骤见第 25.13 节,这里只补充插件层面的要点。

  • 该插件声明响应头、响应流、响应整包、响应结束四个钩子,失败策略为「失败关闭」,插件超时或出错时会拒绝请求。
  • 绑定时服务类型选「模型分组」;按需先绑定到试点分组,核对流式与非流式输出都正常后再扩大范围。
  • 响应头 aigc 中的 ProduceID 即网关请求号,可据此在调用详情中查到对应调用。

27.8 用访问密钥调用开放 API

适用场景:把查询和配置操作纳入脚本、CI 流水线或自建智能体。访问密钥的权限与创建人本人相同。

创建访问密钥

  1. 在顶部导航进入「首页」,在左侧「个人设置」分组中点「访问密钥」。
  2. 点「创建访问密钥」,填写「名称」(只用于辨认,不影响权限)。
  3. 页面一次性显示 AccessKeyId 与 SecretAccessKey,立即保存 SecretAccessKey,关闭后无法再次查看。

列表显示名称、AccessKeyId、创建人、创建时间、最后使用与状态;不再使用时点「撤销」,撤销后下一次调用即失效。平台账号(不属于任何租户的平台管理员)同样可以在「首页」的访问密钥分区创建密钥。

图 27-8 访问密钥页面:上方为「怎么签名调用」的可折叠示例,下方为密钥列表与创建入口

签名调用:每次请求携带三个请求头:

  • x-zenova-date:UTC 时间,格式 YYYYMMDDTHHMMSSZ,与服务端相差不超过 5 分钟;
  • x-zenova-nonce:每次唯一的随机串;
  • Authorization: ZENOVA-HMAC-SHA256 Credential=<AccessKeyId>, SignedHeaders=host;x-zenova-date;x-zenova-nonce, Signature=<签名>。

签名步骤:

  1. 构造规范请求,由六部分按换行连接:请求方法、路径、规范化查询串(按名称和值升序并做百分号编码,无查询串时为空行)、按名称排序的签名请求头(每行 小写名:值,该段以换行结尾)、签名请求头名称列表(分号连接)、请求体的 SHA-256 十六进制摘要。
  2. 构造待签字符串,共三行:ZENOVA-HMAC-SHA256、x-zenova-date 的值、规范请求的 SHA-256 摘要。
  3. 用 SecretAccessKey 对待签字符串做 HMAC-SHA256,结果取十六进制即为签名。

「访问密钥」页面的「怎么签名调用」提供 curl、Node、Python、Go 与命令行工具的示例,可以直接复制;示例中的日期格式已是服务端要求的写法。

你会看到:签名正确时返回 200,密钥列表的「最后使用」随即更新,读取类接口的结果与管理后台一致。签名错误时返回 401,错误码含义如下。

错误码含义
:--:--
SIGNATURE_MALFORMED请求头格式不正确,如日期格式不符
SIGNATURE_MISMATCH签名与服务端计算结果不一致,通常是密钥错误或规范请求拼接有误
SIGNATURE_EXPIRED请求时间超出允许偏差
NONCE_REPLAYED该随机串已被使用过
UNAUTHENTICATED未携带凭据

注意

  • 请求体的摘要参与签名,签名之后再修改请求体(哪怕只改一个字段)会被判为 SIGNATURE_MISMATCH。
  • 访问密钥可以签名调用平台管理 MCP(POST /api/v1/mcp),按调用者的真实身份执行;但模型网关不接受签名,只认 Bearer API 密钥,调用模型请使用绑定模型分组的 API 密钥(第 20 章)。
  • 密钥应存放在密钥管理系统中,不得写入代码仓库或日志。
  • 平台的 OpenAPI 规范只对平台管理员开放:平台管理员登录后,在账号菜单中选择「接口文档」打开在线文档(/api/docs/),规范文件地址为 /api/openapi.json;其他身份访问会被拒绝。规范中列出的接口不代表当前身份有权调用。

27.9 访问域名与证书

适用场景:让调用方通过企业自己的域名或平台分配的子域名访问网关,并按路径把请求交给指定的流量规则。

操作步骤

  1. 打开「网关域名接入」页(不在侧栏中:在「运行总览 › 会话」打开一场会话,会话详情的网关提示条显示「本会话没有经过网关的请求。……」时,点提示条上的「查看接入方式」进入)。页面有「域名」「证书」「防护规则」三个页签。
  2. 在「域名」页签点「声明自定义域名」或「分配平台子域名」。列表显示主机名、状态、协议、证书、路由绑定数、验证方式、路由目标与创建时间。
  3. 打开域名的「查看」,在「路由绑定」中选择匹配方式(路径前缀或精确路径)、填写路径,把「路由目标」选为一条流量规则并「添加」。
  4. 用「路由试算」输入路径与协议,确认会命中哪条绑定。
图 27-9 网关域名接入的域名页签:列出主机名、状态、协议、证书、路由绑定数与验证方式

你会看到:「证书」页签列出当前可用的证书;域名列表的协议列显示接入协议,路由绑定数显示已配置的绑定条数。

注意:域名通常是平台级共享对象,声明、绑定与释放会影响真实流量,变更前请与平台管理员确认;路由试算反映的是配置,不是运行中的流量。证书的新增与更换属于部署侧操作,需要时联系平台管理员。

27.10 来源网段与路径的访问控制

流量规则提供「客户端 CIDR」与「请求路径」两个条件,配合「拒绝本次调用」与「放行」两个动作即可实现黑白名单;平台没有独立的名单入口。

前提:建议规则的第一个条件为「模型分组」属于目标分组,与网段或路径条件取「且」,避免影响其他分组。

黑名单

  1. 新建规则,条件为「模型分组」属于目标分组 +「客户端 CIDR」属于某个网段。
  2. 动作选「拒绝本次调用」并填写原因码,保存并确认。
  3. 需要按路径限制时,把条件换成「请求路径」等于某路径或以某前缀开头,动作同样选拒绝。
图 27-10 网段与路径的拒绝规则:条件为模型分组加客户端 CIDR,动作为拒绝本次调用

白名单

  1. 先建一条「放行」规则:条件为「模型分组」属于目标分组 +「客户端 CIDR」属于允许的网段,命中后结束匹配;把它排在前面。
  2. 在其后排一条兜底的「拒绝本次调用」规则:条件只限定「模型分组」属于目标分组,原因码写明「不在名单内」。

大陆来源限制:在「客户端 CIDR」中勾选「中国大陆」,无需逐个填写网段。只拦截已识别的非大陆来源,可选「不属于」并配「拒绝本次调用」;严格只允许大陆来源,使用前面的两条白名单规则,把允许的网段换成「中国大陆」,未识别、内网或缺少可信来源 IP 的请求由后面的兜底规则拒绝。预置范围支持 IPv4 与 IPv6,不含港澳台;判断依据是访问出口 IP,无法据此确认使用代理的用户实际所在地。

图 27-11 白名单与兜底拒绝两条规则并排:放行规则在前,兜底拒绝在后

你会看到:名单外的请求返回 403 permission_denied,deniedBy 为 routePolicy,details 中带配置的原因码;名单内的请求正常返回。带 X-Forwarded-For、X-Real-IP 或 Forwarded 等伪造来源头的请求无法绕过,判定使用的是网关实际看到的客户端地址。

注意:平台没有「默认拒绝」开关,白名单要按上面两条规则组合实现;没有转发目标的普通规则是增强规则、不会结束判定,不能代替「放行」。被拒绝的请求同样记入「运行总览 › 请求」,状态为「已拦截」,可以按接入凭据筛选追溯。

27.11 跨租户隔离

适用场景:评估多租户部署下各租户的数据与配置是否相互隔离。

你会看到:租户与身份只从已验证的会话推导,客户端自行添加的租户、根权限或用户标识请求头一律被忽略;用不属于本租户的资源编号请求时返回 404 而不是「无权限」,不泄露资源是否存在;平台级接口对租户管理员返回 403。

越权尝试结果
:--:--
正常列出本租户模型分组200,结果全部属于本租户
附加伪造的租户、组织、用户或根权限请求头200,仍是本租户数据,未提权
读取不属于本租户的资源编号404,不透露存在性
访问平台级租户列表,或附加伪造的根权限头403 PERMISSION_DENIED
在路径中放入其他租户的编号404

注意:数据库层另有按租户的行级隔离策略,业务查询只会命中本租户的数据。跨租户验证属于平台运维范畴,需要在独立环境准备两个租户后由交付方执行,租户侧不需要也不应自行探测。

27.12 集成上线检查

  • 插件所需权限已声明,绑定范围与失败策略已确认,「执行统计」中有预期的执行记录;新版本已在试点范围核对,旧版本可以切回。
  • 请求与响应改写已分别用命中与不命中、流式与非流式请求核对,改写失败处理已按业务要求设置。
  • AI 生成内容标识已在流式与非流式输出中核对;内置策略规则的命中顺序已在「确认变更」中核对。
  • 访问密钥已存入密钥管理系统,按最小权限账号创建,不再使用的已撤销;客户端已处理 401、403、429 等错误响应。
  • 域名与路由绑定已通过「路由试算」核对,变更已与平台管理员确认。

能力说明

不提供的能力替代做法
:--:--
在管理后台按单个接口启用或禁用平台管理 API用角色权限域限制调用方可用的接口范围,或撤销访问密钥使其整体失效(27.8 节)
访问密钥按接口勾选权限范围为自动化任务单独创建权限最小的账号,再用该账号创建访问密钥(27.8 节)
可自定义时间窗与随机串有效期的防重放策略平台已内置时间窗校验与随机串防重放;需要更强策略时由调用方或上游系统实现(27.8 节)
独立的 IP 与路径黑白名单入口,以及在 API 密钥上直接绑定 IP用流量规则的「客户端 CIDR」与「请求路径」条件配合「拒绝 / 放行」动作实现(27.10 节)
任意国家或地域的自定义选择器「客户端 CIDR」提供「中国大陆」系统预置;其他地区可填写具体网段,或在接入层配置地域限制(27.10 节)
租户侧的 Web 应用防护(WAF)规则集配置页应用层攻击防护在部署层由平台统一实施,需要调整时联系平台管理员
网关到上游的双向 TLS(客户端证书)上游用 HTTPS 单向认证配合 API 密钥或 OAuth;确需双向 TLS 时,在网关之外用支持双向 TLS 的出口代理完成
引用外部 KMS 或 Vault 中的密钥上游凭据由平台加密存储,界面与接口只回显指纹;轮换时在供应商账号中更新
流式增量片段的响应体改写响应体格式化只作用于非流式最终响应;需要处理流式输出时开发声明「响应流」钩子的网关插件(27.2 节)
插件内的持久状态、熔断、并发计数与签名校验宿主函数并发与熔断使用流量规则的「应用限额」(第 26 章);其余逻辑由上游系统承担
插件包直接以源码压缩包上传按 SDK 的 README 用 zr-plugin build 生成插件包后再上传(27.2 节)

---

上一章:26. 流量规则与流量保护 · 下一章:28. 用量与成本