03 查看者强制只读代理


文档摘要

03 查看者强制只读代理 本节摘要:这是第 4 章最硬核的一节。viewer 的「只读」怎么保证?不是靠前端隐藏写按钮(前端可被绕过),而是在服务端代理引擎请求的层强制把关——viewer 的非 GET/HEAD 请求直接拒绝。本节讲清这套「反代层强制只读」,并论证为什么「靠前端隐藏」永远不够。 一、为什么 viewer 只读是真问题 先看为什么这件事需要特别强调。viewer 是「只读」scope,但「只读」这个约束怎么落实? 朴素想法:前端隐藏写按钮,viewer 用户看不到,就改不了。 问题:前端可以被绕过。 考虑攻击场景: 所以「靠前端隐藏」是不够的——只要服务端不强制,任何人拿 viewer 令牌都能绕过前端直接调写接口。真正的只读必须在服务端强制。

03 查看者强制只读代理

本节摘要:这是第 4 章最硬核的一节。viewer 的「只读」怎么保证?不是靠前端隐藏写按钮(前端可被绕过),而是在服务端代理引擎请求的层强制把关——viewer 的非 GET/HEAD 请求直接拒绝。本节讲清这套「反代层强制只读」,并论证为什么「靠前端隐藏」永远不够。

一、为什么 viewer 只读是真问题

先看为什么这件事需要特别强调。viewer 是「只读」scope,但「只读」这个约束怎么落实?

  • 朴素想法:前端隐藏写按钮,viewer 用户看不到,就改不了。
  • 问题:前端可以被绕过

考虑攻击场景:

恶意用户拿到 viewer 令牌 │ ▼ 不走前端(前端隐藏了写按钮) │ ▼ 直接用工具(如 curl)调服务端的写接口 │ ▼ 如果服务端不检查 ──► 写操作成功!viewer 「只读」被绕过

所以「靠前端隐藏」是不够的——只要服务端不强制,任何人拿 viewer 令牌都能绕过前端直接调写接口。真正的只读必须在服务端强制。

二、OpenWork 的做法:反代层强制

OpenWork 在哪一层强制 viewer 只读?在服务端代理引擎请求的层(第 3 章 03 节)。逻辑很简单:

服务端收到请求(带 viewer 令牌) │ ▼ 即将代理给引擎 │ ▼ 检查:scope == viewer 且 方法 != GET/HEAD? │ ├─ 是 ──► 拒绝(403, viewer 只读) │ └─ 否 ──► 继续代理

也就是说,viewer 令牌的任何写操作(POST/PUT/DELETE 等,以及非 GET/HEAD 的方法),在「即将转发给引擎」时被服务端硬性拒绝。

这个检查在反代层,意味着:

  • 不管请求从哪来(前端、curl、任意客户端),都过这个检查。
  • viewer 无法绕过——因为它在服务端,不在客户端。

三、为什么在反代层(而不是业务层)

你可能会问:为什么不每个业务 handler 自己检查 scope?要在反代层统一检查?两个理由:

1. 集中且不漏

反代层是「所有引擎请求的必经之路」。在这里检查,保证没有漏网之鱼——不管哪个 handler、哪个路径,只要方法非 GET/HEAD 且 viewer,一律拒绝。如果在每个 handler 自己检查,容易漏(某个 handler 忘了写检查)。

2. 早拒绝省资源

反代层在「转发给引擎之前」检查,如果拒绝,请求根本不会到引擎——省了引擎那边的开销。如果在业务层(handler 里)检查,请求已经过了一些处理才被拒,浪费。

四、一个例子走一遍

用例子感受这套强制:

viewer 用户想删一个文件(写操作) │ ▼ 用 curl 直接调服务端写接口(绕过前端) DELETE /workspace/abc/session/.../file Authorization: Bearer owt_xxx(viewer) │ ▼ 服务端收到,即将代理给引擎 │ ▼ 反代层检查:scope=viewer 且方法=DELETE(非 GET/HEAD) │ ▼ 拒绝!403 Forbidden「viewer 只读」 │ ◄─ viewer 用户:操作被拒

不管 viewer 用户怎么绕前端,服务端反代层都会拦下来。这才是「真只读」。

五、「靠前端隐藏」为什么永远不够

这是本节要传递的核心认知,值得反复强调。「靠前端隐藏」的安全措施为什么永远不够:

问题 后果
前端可被绕过(用 curl/工具直调 API) 隐藏的写操作能被直接调用
前端代码可被改(浏览器开发者工具) 隐藏的按钮能被显示出来
前端逻辑可被改 限制条件能被去掉

前端是「用户体验」层,不是「安全」层。前端隐藏按钮是为了「不让用户误点」,不是「防恶意」。真正的安全必须在服务端——因为服务端是攻击者够不到的地方。

⚠️ 黄金法则:任何安全约束,都必须在服务端(或更下层)强制,前端只是「锦上添花」。OpenWork 的 viewer 只读在反代层强制,正是这条法则的体现。

六、collaborator 的特殊性(权限回复)

这里有个细节值得提:虽然 viewer 被强制只读,但 collaborator 必须能回复权限询问(因为 collaborator 能写,写操作可能触发 Agent 的权限询问,collaborator 要能回复)。

所以在反代层的检查里,对「权限回复」这种特殊路径,collaborator 是放行的(它需要回复询问才能继续干活)。这是「只读强制」与「权限询问协作」之间的细微平衡——viewer 全禁,collaborator 在权限询问这条特殊路径放行。

七、本节要点回顾

  1. viewer 只读是真问题:前端隐藏可被绕过,必须在服务端强制。
  2. 反代层强制:viewer 非 GET/HEAD 请求,在「即将转发给引擎」时被拒。
  3. 集中且不漏:反代层是必经之路,所有引擎请求都过这个检查。
  4. 早拒绝省资源:拒在转发前,不到引擎,省开销。
  5. 靠前端隐藏永远不够:前端可绕过/可改,只是 UX 层不是安全层。
  6. 黄金法则:安全约束必须在服务端强制,前端只是锦上添花。
  7. collaborator 特殊:权限回复路径放行(它需要回复询问干活)。

只读强制讲清了,最后一节讲审批模式与令牌服务。


发布者: 作者: 灏天文库 转发
评论区 (0)
U