对象级授权与认证的边界差异
在接口设计阶段落地 OWASP API 安全 Top 10:以对象级授权(BOLA)防护为例
认证回答的是“请求来自谁”,对象级授权回答的是“这个已确认的身份能不能操作这一个具体对象”。两个问题的答案来自完全不同的地方,但接口设计文档里常常只有一行“需要 Token”,把它们压成了同一件事。结果是把 URL 里的一个 ID 换成另一个就能读到别人的数据,而认证层从头到尾都在正常工作。失效对象级授权在 OWASP API 安全 Top 10 中排在 API1:2023 的位置,一个重要原因就是这类缺陷不需要绕过认证,也不产生异常特征——日志里看到的是一个合法用户的一次合法请求。
边界落在哪一层
认证之所以能在网关、中间件或统一框架层收敛,是因为它只需要验证凭据本身的有效性,判断依据在请求里就是完整的。对象归属关系不具备这个性质:某个订单属于哪个用户、哪个租户、挂在哪个上级资源之下,只存在于业务数据中,只有能查到这份数据的代码才能作出判断。网关知道请求带着一个有效身份,但不知道路径里那个 ID 归谁。任何试图在统一入口一次性解决授权的设计,在按 ID 操作的接口上都会留下缺口,这不是实现疏漏,而是信息在那一层根本不可得。
由此还产生了一个容易被误读的推论:“已经有一层安全”并不构成对象级授权的替代。同理,用不可预测的标识替代连续自增 ID 只提高了猜测成本,它改变的是攻击效率,不是授权判断是否存在。评审时把“我们用了随机 ID”当作归属校验的答案,等于承认这一项没有答案。
时间维度上的差异
认证在会话建立时完成一次,之后由凭据延续;对象级授权没有这种延续性。详情页打开时校验过归属,不能让提交环节默认“已经确认过”——调用者可以直接构造提交请求,跳过任何前置步骤。多步流程的每一步都需要独立校验,中间态令牌证明的是流程连续性,不是操作权限。更进一步,拥有一个对象也不等于有权执行它的每一种状态转换,这一层判断仍在对象授权的范围之内,却常常连边界都没被划出来。
在实现上,把边界稳定下来的做法是让归属条件成为数据访问的固有部分:查询条件同时包含对象标识和当前身份,越权请求自然查不到数据;更新与删除同样把条件写进语句本身,而不是先查出对象再比对。相应地,对无权访问的对象返回“不存在”,可以避免通过响应差异反推对象是否存在;若业务上必须区分,就该在文档里明确这是有意接受的信息暴露。
区分这两条边界的成本很低。在接口设计文档里给每个带对象标识的接口补上“归属字段”和“校验位置”两栏,填不出来的那几行,就是认证被当成授权用了的地方。

参与讨论
IDOR在日志里全是合法请求,这类问题最难排查