吾码AI视频TaskHandle与FileHandle四道隔离示意图

创建意图、异步任务、临时文件和正式资产各有一个最小输入,不能被一个供应商ID替代。

摘要| 调用AI视频时,前端为什么只拿到TaskHandle,成功后又换成FileHandle,而不是直接返回供应商任务ID和临时URL?本文基于Microi吾码当前源码、5项客户端测试以及有效与篡改句柄的在线回读,拆解客户端去敏、当前会话收口、双句柄分权和管理员HDFS持久化四道边界,并给出超时恢复与发布接入的实用步骤。

① 一个供应商ID看似省事,却把四种状态揉成了一个字段

AI视频不是同步下载接口。一次业务意图先创建异步任务,任务成功后才出现临时文件,临时文件再经过平台持久化才成为可发布资产。把供应商任务ID直接交给前端,等于让页面同时知道供应商标识、任务映射和后续文件领取线索。

吾码当前契约把它们拆开:RequestId负责业务防重,TaskHandle负责查任务,FileHandle负责取文件,最终HDFS地址才交给发布连接器。每一步只携带完成当前动作所需的最小信息。

AI视频从稳定RequestId到TaskHandle、FileHandle和租户HDFS的生命周期

两种句柄不是重复设计:一个描述任务查询能力,一个描述成功文件领取能力。

核心判断| 供应商ID回答“上游叫什么”;平台句柄回答“当前用户此刻被允许做哪一步”。

② 第一道隔离:客户端先把伪造身份和供应商凭据删掉

当前v8-ai.js会先复制业务参数,再删除OsClient、CurrentUserId、ApiKey、Endpoint、Headers、Token、Authorization等字段。调用者即使在可编辑脚本里塞入另一个租户或自带Key,也不会原样进入平台AI端点。

await V8.AI.GetMiniMaxVideoTask({
  TaskHandle: taskHandle,
  OsClient: 'forged-tenant',
  ApiKey: 'forged-key',
  Authorization: 'forged-token'
});
// 实际保留:{ TaskHandle }
// 固定路由:POST /api/Ai/GetMiniMaxVideoTask

AI视频业务参数、会话上下文、供应商凭据和正式资产边界矩阵

前端负责表达业务意图;用户、租户、Key与资产归属必须在可信后端确定。

边界一| 去掉敏感参数不是为了让请求更短,而是防止调用方覆盖平台的真实身份与供应商配置。

③ 第二道隔离:服务端每次都从当前会话重新解析用户和租户

CreateMiniMaxVideo、GetMiniMaxVideoTask和GetMiniMaxVideoFile都不是相信前端传来的UserId或OsClient。控制器先读取当前会话,再把userId与osClient交给受保护服务。句柄因此不是脱离登录态的万能票据。

  1. 创建:当前用户 + 当前OsClient + 稳定RequestId组成业务上下文。
  2. 查任务:当前用户 + 当前OsClient + TaskHandle进入查询。
  3. 取文件:当前用户 + 当前OsClient + FileHandle进入临时文件读取。
  4. 持久化:额外要求PlatformAdminOnly,再写入当前租户公有HDFS。

边界二| 句柄必须和当前会话一起解释;文章不把它描述成可跨用户、跨租户或永久使用的通用能力令牌。

④ 第三道隔离:TaskHandle只查任务,FileHandle只取成功文件

服务端参数类把职责写得非常窄:MiniMaxVideoTaskParam只有TaskHandle,MiniMaxVideoFileParam只有FileHandle。任务尚未成功时,没有必要把文件能力提前交给前端;任务成功后,状态响应再返回FileHandle。

public sealed class MiniMaxVideoTaskParam
{
    public string TaskHandle { get; set; }
}

public sealed class MiniMaxVideoFileParam
{
    public string FileHandle { get; set; }
}

这也让接口更容易审计:查状态的请求体里如果出现Endpoint、ApiKey或供应商任务ID,本身就偏离了平台契约。文件接口同理,不接受TaskHandle去猜文件,也不让前端拼临时供应商地址。

边界三| 双句柄把“知道任务状态”和“领取成功文件”分成两个动作,避免一个标识拥有过多含义。

⑤ 正反两个在线探针:HTTP 200不代表句柄有效

本轮在当前登录会话做了三次只读回读。伪造TaskHandle返回HTTP 200但业务Code=0,提示句柄无效、被篡改或创建后Key发生变化;伪造FileHandle同样被拒绝。随后用本轮真实任务的TaskHandle查询,Code=1、Status=Success,并返回FileHandle。

有效与篡改AI视频句柄的在线回读证据卡

传输层成功只说明请求到达;业务Code、Status和返回字段才能说明句柄是否通过。

伪造 TaskHandle → HTTP 200 / Code 0 / 明确拒绝
伪造 FileHandle → HTTP 200 / Code 0 / 明确拒绝
有效 TaskHandle → HTTP 200 / Code 1 / Status Success / 返回 FileHandle

证据边界| 探针证明当前服务会校验句柄并拒绝篡改;它不等于公开了具体签名算法或供应商内部ID格式。

⑥ 第四道隔离:临时文件必须转成当前租户的正式资产

成功状态返回FileHandle仍不代表文章可以直接发布。供应商文件通常是临时资源,生命周期与访问策略不由内容平台控制。吾码的PersistMiniMaxVideoFile要求PlatformAdminOnly,从当前DiyToken读取用户与OsClient,再把文件转存到本租户公有HDFS。

  • 临时地址用于受控拉取,不写进长期文章正文。
  • 持久化结果进入当前租户命名空间,发布连接器只读取稳定地址。
  • 管理员权限保护的是资产落库动作,不替代前面的任务与文件句柄校验。
  • 源码存在、任务成功、文件持久化和公开CDN可读要分别验收。

边界四| FileHandle是过渡能力,HDFS地址才是可交付资产;二者不能因为都指向视频而混为一谈。

⑦ 超时恢复教程:保留原键、查询原句柄、拒绝随机重试

视频创建最危险的故障不是明确失败,而是客户端超时、上游却可能已经接单。此时换一个随机RequestId重发,会把同一镜头变成两个真实任务。正确恢复流程是保留原业务槽位和原RequestId,优先读取已有TaskHandle;没有终态就继续查旧任务。

AI视频创建超时后的稳定键和句柄恢复流程

恢复的目标是找回同一件事,而不是用一个新标识再做一遍。

1. 创建前:story + shot + version → 稳定 RequestId
2. 返回未知:记录未知,不生成 retry-2 或随机 UUID
3. 已有 TaskHandle:持续查询原任务
4. Status=Success:只使用响应中的 FileHandle
5. 管理员持久化:转入当前租户 HDFS
6. CDN与字节回读成功:才交给发布连接器

操作心得| 幂等键解决“是不是同一件事”,TaskHandle解决“它做到哪一步”,FileHandle解决“成功文件怎么领”。

⑧ 5项测试通过之后,还要把验收事实分层

本轮执行v8-ai.spec.mjs,5项通过、0失败、0跳过。相关用例固定了客户端去敏、固定平台路由以及任务/文件只透传对应句柄的契约;在线正反探针则证明当前服务实际按这套契约响应。

  1. 源码事实:参数被删除、端点固定、服务端重新读取会话。
  2. 测试事实:5/5通过,伪造字段不会进入平台请求。
  3. 在线事实:篡改句柄被拒绝,有效句柄返回Success与FileHandle。
  4. 资产事实:只有管理员持久化并通过CDN回读,才算可发布。

因此,“不给供应商ID”不是少返回一个字段,而是把上游实现、当前会话、异步任务和正式资产隔离开。系统既能在超时后找回原任务,也不必把供应商密钥与内部标识暴露给可编辑前端。

最终结论| RequestId防重,TaskHandle查状态,FileHandle取结果,HDFS负责交付;四层各守一段边界。

Logo

宁波官方开源宣传和活动阵地,欢迎各位和我们共建开源生态体系!

更多推荐