已经登录 BailingHub,为什么 AI 还是不能查询订单?匿名预览与业务身份不是一回事

一位开发者在 BailingHub 在线体验中导入了演示订单数据,然后打开聊天入口,输入:

text 复制代码
只查询订单 SO-1001,并返回订单状态。

AI 没有查询订单,而是提示需要先登录。

问题是:开发者明明已经登录了 BailingHub 控制台,页面上也没有第二个登录按钮。

这不是订单工具坏了,也不是要求用户再注册一次 BailingHub。

真正发生的是:

text 复制代码
中枢管理员已经登录
≠ 聊天窗口已经知道当前业务用户是谁
≠ 当前业务用户有权查询这张订单

这个问题后来成为 BailingHub 公开仓库的 Issue #47,也推动 v0.3.4 把控制台中的"试聊"明确改成"匿名预览"。

这篇文章不讨论怎样把登录按钮画得更明显,而是拆开三个经常被混为一谈的身份:

text 复制代码
BailingHub 管理员
聊天访客 / 业务操作主体
业务系统最终授权对象

只有把三者分开,AI 才不会因为"某个人已经登录某个后台"就获得它不该拥有的业务权限。

一、先回答最容易误解的问题:这是不是 Bug?

"匿名聊天入口没有业务登录态"本身不是 Bug。

聊天入口可能被嵌入:

  • 商城商品页;
  • CRM 客户详情页;
  • ERP 工作台;
  • 企业内部系统;
  • 一个完全公开的网站。

BailingHub 不能凭空知道打开组件的人是谁,也不能因为浏览器里同时登录了中枢控制台,就假设这个人是商城用户、客户经理或门店管理员。

真正的产品缺口是旧引导没有把这件事说清:

  • 按钮叫"试聊",容易让人以为可以验证全部工具;
  • AI 只说"请先登录",容易让人寻找一个不存在的登录入口;
  • 上手向导没有充分强调演示主体 Smoke 与匿名聊天的区别。

所以 v0.3.4 修复的是引导和失败语义,不是放宽身份闸门。

二、三种身份分别控制什么

1. BailingHub 管理员身份

管理员登录 /console/ 后,可以按照自己的后台角色管理:

  • 调度目标;
  • 模型凭证;
  • 路由;
  • 工具源;
  • 接入方;
  • 聊天入口;
  • 任务与 Trace;
  • 审批和审计记录。

它解决的是:

谁可以配置和运维这套中枢?

它不自动回答:

当前聊天窗口里的访客,在商城里是谁?

2. 聊天访客与业务操作主体

聊天组件需要区分两件事:

  • 这个匿名浏览器是不是上一轮对话的同一个访客;
  • 这个访客是否已经被业务系统可信地识别。

前者可以用随机 visitor_id 维持会话连续性;后者必须来自业务系统后端签发并由中枢验真的短期身份票据。

text 复制代码
visitor_id = 会话连续性
signed ticket = 可信业务主体

二者不能互换。

3. 业务系统最终授权

即使票据已经证明当前操作主体是 tenant-a:user-42,也不表示他一定有权查询订单 SO-1001

业务系统仍需判断:

  • 用户是否存在、启用且未过期;
  • 当前角色是否有订单查询权限;
  • 数据范围是否包含这张订单;
  • 租户、门店或组织边界是否匹配;
  • 对象当前状态是否允许操作。

票据解决"代表谁",业务系统解决"这个人现在能不能做"。

三、为什么不能把中枢管理员自动变成业务用户

假设一个 BailingHub 管理员同时接入三个系统:

text 复制代码
商城 A
CRM B
ERP C

如果中枢把管理员登录态自动转成业务主体,系统必须猜测:

  • 他在三个系统里的用户 ID 是否相同;
  • 当前应该属于哪个租户;
  • 在商城是管理员,在 CRM 是否仍有同级权限;
  • 后台角色怎样映射成订单、客户和库存的数据范围;
  • 管理中枢是否等于有权操作全部业务数据。

这些推断没有可靠依据。

更危险的是,中枢管理员通常拥有工具和路由配置权。如果这种身份再自动变成所有业务系统的高权限用户,配置权限与业务操作权限就被合并到了同一个入口。

因此合理边界是:

text 复制代码
中枢管理员登录态
只用于中枢管理

业务操作主体
必须由对应业务系统的可信边界提供

四、匿名预览究竟能验证什么

BailingHub 控制台为聊天入口提供独立预览链接。v0.3.4 将它明确命名为"匿名预览"。

它适合验证:

  • Widget 能否加载;
  • 页面允许域名与基础限速是否正常;
  • 问候语、外观和交互是否符合预期;
  • 公开问答是否可用;
  • 不要求主体的工具能否进入候选集合;
  • 匿名访客的会话连续性是否正常。

它不适合验证:

  • 私有订单查询;
  • 会员资料读取;
  • 用户地址修改;
  • 售后申请;
  • 退款、库存和其他要求可信主体的业务动作。

匿名预览没有独立业务登录入口,也不会继承控制台 Cookie。

这不是"少做了一次自动登录",而是刻意保持了信任边界。

五、没有可信主体时,为什么连只读订单工具也要隐藏

很多人会问:

查询又不会改数据,为什么匿名时不能先让 Agent 调一下?

只读不等于公开。

订单状态、收货信息、客户资料、员工档案和财务数据,即使只读,也可能属于私有数据。

演示订单工具在能力声明中要求:

yaml 复制代码
subject:
  required: true

当会话没有可信业务主体时,BailingHub 的工具装配会返回主体锁定状态。运行时不会把这些工具的名称、描述和参数 Schema 继续交给 Agent。

可以把候选集合抽象为:

text 复制代码
业务系统声明的工具
∩ 路由允许的 scope
∩ 当前身份与治理条件
= Agent 当前实际可见工具

隐藏工具不能替代业务 API 的最终鉴权,但可以避免 Agent 围绕当前无法合法执行的能力规划、组参数或作出承诺。

六、为什么 visitor_id 不能当作用户身份

匿名组件通常需要一个标识来续接对话。BailingHub 会接受或生成一个受限格式的 visitor_id,用于把同一浏览器的消息放进同一会话范围。

但它可以由客户端提交,本质上只是会话线索。

如果把它当作业务身份,攻击者只需要改成另一个值,就可能尝试读取别人的订单。

因此:

text 复制代码
visitor_id
可以参与匿名会话连续性
不能参与业务权限放行

页面 URL、标题、thread_id 和其他客户端上下文也一样:它们可以帮助 Agent 理解页面与会话,但不能作为权限证据。

七、在线体验为什么要使用"演示主体 Smoke"

在线体验需要让开发者验证订单工具,但又不能把一个带固定身份的公共聊天链接开放给所有人。

BailingHub 采用的做法是把两条路径分开:

text 复制代码
匿名预览
用于组件、公开问答与无主体能力

演示主体 Smoke
由服务端携带受控演示主体,验证需主体工具、job 与 Trace

在在线体验中,正确验证方式是:

text 复制代码
进入「上手向导」
-> 导入演示配置
-> 点击「运行演示主体 Smoke」
-> 打开任务与 Trace 查看真实调用

导入配置本身不会自动运行任务,也不会把当前管理员提升成订单用户。

共享体验环境使用 stateless-readonly profile,只开放受控的只读演示范围;本地 full-local Demo 才包含创建工单、退款审批和故障工具等更完整链路。

八、正式接入时,业务身份怎样进入 BailingHub

正式网页接入的信任链应该从业务系统自己的登录态开始:

text 复制代码
用户登录商城 / CRM / ERP
-> 业务后端确认当前 Session
-> 业务后端用接入方 token 签发短期票据
-> 页面只输出短期 ticket
-> Widget 通过 data-ticket 携带
-> BailingHub 验签并取得 uid
-> uid 进入可信任务元数据
-> 工具调用以 On-Behalf-Of 传给业务系统
-> 业务系统做最终授权

票据载荷可以包含受控的主体标识与过期时间,例如:

json 复制代码
{
  "uid": "tenant-a:user-42",
  "exp": 1787000000
}

关键不是字段长什么样,而是:

  • 票据必须由业务后端签发;
  • 签发动作发生在业务系统已确认登录态之后;
  • 接入方 token 永远不进入浏览器;
  • 票据有效期应当有限;
  • 中枢必须验签;
  • 验签失败不能静默降级成匿名身份继续执行私有工具。

控制台的聊天入口可以配置"业务身份票据签发方"。这只表示该入口接受哪个接入方签发的票据,并不表示系统会自动生成一个业务用户。

九、为什么坏票据要返回 401,而不是悄悄当匿名访客

假设业务页面原本应该携带身份票据,但由于缓存、时钟或代码错误,发来了无效 ticket。

如果中枢静默降级为匿名会话,表面上聊天还能继续,真正的问题却被掩盖了:

  • 用户以为自己处于登录状态;
  • Agent 看不到私有工具;
  • 产品只返回模糊的"请先登录";
  • 接入方很难定位票据已经失效。

BailingHub 对无效、过期或不属于当前入口的票据明确失败,不把它当成"没传票据"。

text 复制代码
没有 ticket:按匿名入口处理
存在但无效的 ticket:明确拒绝
有效 ticket:建立可信主体

这让集成错误能够尽早暴露。

十、可信票据也不是最终业务授权

票据验签成功后,需主体工具可以进入候选集合,但仍然不能跳过业务系统。

完整链路应该是:

text 复制代码
票据验真
-> 建立可信主体
-> 路由与 scope 计算工具范围
-> Agent 选择工具并生成参数
-> 中枢签名调用业务系统
-> 业务系统验证 On-Behalf-Of 主体
-> 业务系统按角色、租户、对象与状态最终裁决

因此下面两种结果都可能正确:

text 复制代码
票据有效,但工具不在当前路由白名单中
票据有效、工具可见,但业务系统拒绝访问当前订单

第一种属于中枢可达范围,第二种属于业务最终 Authority。不能用"已经登录"覆盖二者。

十一、主体缺失时,Agent 应该怎样回答

旧的泛化提示容易说:

text 复制代码
请先登录系统,登录后自动携带身份。

但匿名预览里并没有独立登录入口,这句话会制造错误期待。

v0.3.4 的运行时引导明确要求:

  • 说明本次会话没有收到业务后端签发的可信身份票据;
  • 说明要求主体的工具当前没有暴露;
  • 不猜测或编造订单数据;
  • 不声称当前聊天框可以自行登录;
  • 不索要账号、密码、Token 或用户 ID;
  • 如果组件嵌入真实业务系统,引导用户返回业务系统完成登录并刷新助手;
  • 说明独立匿名预览不能自行解锁私有能力。

这仍是一层面向用户的解释。真正的安全边界来自工具装配、票据验签和业务授权,而不是提示词本身。

十二、v0.3.4 到底改了什么

这个版本没有新增身份协议,也没有改变票据格式。

它主要收口了四个产品语义:

1. "试聊"改成"匿名预览"

入口名称直接表达它没有业务身份。

2. 控制台常驻说明身份边界

聊天入口列表、嵌入弹窗与预览页都会说明:中枢管理员不会自动变成业务用户。

3. 演示验证与匿名预览分流

上手向导把"运行演示主体 Smoke"作为导入后的明确动作,避免使用者在匿名聊天框里寻找登录入口。

4. 无主体回答不再制造错误恢复路径

Agent 不会要求用户在匿名预览中完成不存在的登录,也不会索取敏感凭据。

安全闸没有放宽:所有 subject.required:true 工具,包括只读和写操作,仍要求可信主体。

十三、六个常见接入错误

错误做法 为什么不成立 正确方向
登录中枢后台后直接打开预览 管理员身份不是业务用户身份 用 Smoke 验证 Demo;正式页面由业务后端签票
visitor_id 当用户 ID 客户端可提交,只能承担会话连续性 使用验签 ticket 建立主体
让模型填写 user_id 模型输出是不可信业务参数 主体由可信运行上下文注入
把接入方 token 放进前端 浏览器中的长期密钥可被读取和滥用 后端保管 token,只向前端输出短票
票据失败时降级为匿名继续 掩盖集成故障和身份漂移 明确 401,刷新登录态后重新签票
验签通过后不做业务鉴权 认证了主体,不等于有当前对象权限 业务系统实时校验角色、数据范围和对象状态

十四、上线前的身份链路测试矩阵

至少验证下面这些情况:

场景 预期结果
匿名预览查询公开知识 正常回答
匿名预览查询私有订单 需主体工具不暴露,不编造结果
控制台管理员登录但无 ticket 仍按匿名访客处理
有效 ticket + 有业务权限 工具进入候选,业务系统允许后返回结果
有效 ticket + 无对象权限 业务系统最终拒绝,不要求重复登录
过期或错误签名 ticket 明确 401,不静默降级
用户在对话里声称"我已登录" 不改变可信主体状态
篡改 visitor_id 不能获得业务权限
token 泄露到前端扫描 构建或安全检查应失败
用户退出业务系统后刷新页面 后端不再签发有效票据,私有能力关闭

只有正常路径和负向路径都通过,身份链路才算接好。

十五、这次真实反馈证明了什么

Issue #47 至少证明了一件事:

一个安全判断可以是正确的,但如果产品没有给出准确的操作路径,使用者仍然会把它理解成 Bug。

这次修复证明:

  • 公开体验中的真实用户已经走到演示订单工具这一步;
  • 匿名预览与需主体工具之间存在真实理解断点;
  • BailingHub v0.3.4 已调整界面和无主体引导;
  • 在线体验已用演示主体 Smoke 验证订单任务与 Trace。

它不证明:

  • 报告者已经完成自己的业务接入;
  • BailingHub 已被该用户或其企业采用;
  • 票据可以替代所有身份系统;
  • 所有工具和业务权限都已经逐项验证。

真实反馈应当推动产品收口,但不能被包装成客户案例。

结语:登录状态不是可以跨系统自动传递的魔法

"用户已经登录"必须补上两个问题:

text 复制代码
登录了哪个系统?
这个系统怎样把可信身份交给下一跳?

BailingHub 管理员登录解决的是中枢配置权;业务后端签发的短期票据解决的是当前聊天访客代表谁;业务系统的实时权限判断解决的是他能否查询或办理当前对象。

三层关系可以写成:

text 复制代码
中枢管理员身份
≠ 业务操作主体
≠ 最终业务授权

匿名预览保持匿名,不是产品少做了一个登录按钮,而是系统拒绝猜测一个不存在的业务身份。

真正可靠的接入方式,是让身份从业务系统的可信登录边界出发,通过短期票据进入中枢,再由业务系统对每一次真实操作保留最终裁决权。

这样,AI 才能在知道"代表谁"的同时,也明确知道"当前还不能做什么"。

延伸阅读与体验

相关推荐
dong_junshuai1 小时前
每天一个开源项目#73 Munder Difflin:2.3K Star 的本地多Agent办公室
开源·github·agent
SL_staff2 小时前
销售知识管理的断点分析与技术解法:从3天找话术到秒级检索
java·开源·github
苏灿烤鱼4 小时前
上下文写成文件系统,为什么向量还能静默丢?
python·github·agent
u1301304 小时前
GitHub 热榜项目:日榜(2026-08-19)
github
AI 编程助手GPT4 小时前
VS Code 1.133 实战:Claude 可免 GitHub 登录,HTML 保存后自动刷新
前端·html·github
问天_观心16 小时前
零基础在windows环境下的WSL使用llamafactory(二)
人工智能·神经网络·语言模型·github·模型蒸馏
逛逛GitHub18 小时前
AI 时代 Markdown 又火了,7 款 GitHub 高赞开源编辑器。
github
u13013018 小时前
GitHub 热榜项目:日榜(2026-08-18)
github