~/VibeHandbook
$39

18 · 04

认证 vs 授权:那个谁都能调的接口

这两个词听起来很像,而二者的区别正是真正的数据泄露藏身之处。

  • 认证(Authentication) 回答的是你是谁?——登录、证明身份。
  • 授权(Authorization) 回答的是你被允许做什么?——这个已登录的用户是否可以对这份数据执行这个操作。

AI 在认证上还算不错;库帮它处理了大部分。授权才是它经常翻车的地方,因为授权是你应用规则所特有的,而 AI 并不知道这些规则。教科书级的灾难:

// VULNERABLE: 检查了你是否登录,却没检查你是谁
app.get("/admin/export-all-users", requireLogin, (req, res) => {
  res.json(db.getAllUsers()); // 任何已登录用户都能打这个接口
});

那个接口是“受保护的”——你必须登录。但任何已登录的用户,包括一个三十秒前才注册的,都能调用它、下载到每一个用户的数据。认证有了,授权没有。修复办法是在操作本身上检查权限:

// SAFE: 确认这个用户确实是管理员
app.get("/admin/export-all-users", requireLogin, (req, res) => {
  if (!req.user.isAdmin) return res.status(403).send("Forbidden");
  res.json(db.getAllUsers());
});

同样的陷阱以缩小版的形式到处出现:一个接口返回订单 #1234,却不检查这个订单是不是属于发起请求的那个用户。任何人都能改一改 URL 里的数字,读到别人的订单。规则一点也不光鲜,但绝对:在每一个接触数据的接口上检查授权,并且不要信任来自客户端的 ID。 不要因为一个 URL 很隐蔽就假定它安全——“没人知道这玩意儿存在”不是一种安全控制手段。

想离线阅读?

获取 PDF + EPUB + 可下载的提示词库 + 版本更新。

$ 获取 PDF — $39