从零构建可收费的付费API:密钥、边缘函数与API设计实战

用Supabase从零搭建按调用计费的付费API,涵盖密钥安全、设计规范与四道防护的完整工程决策。
本文梳理了一套基于Supabase构建生产级付费API的完整方案。核心安全铁律是密钥只存SHA256哈希、仅在服务端生成、通过边缘函数守门,数据库永不直接暴露公网。文章解释了为何Supabase自带的JWT方案不适用于API密钥场景——JWT无法即时撤销,而自建哈希查询体系可做到删除记录即吊销权限。在API设计层面,强调名词复数端点、诚实状态码、默认分页,以及从第一天起引入版本号以避免破坏性变更。安全防护方面覆盖用户级速率限制、防SQL注入、CORS来源控制和强制HTTPS四个维度。最终,清晰的「复制粘贴即成功」文档被视为激活付费用户的关键触点。
把一张普通的数据表变成能对外收费的公共API,是很多独立开发者眼中「睡后收入」的理想形态。B站UP主Oliver(曾参与Response AI等软件工具)在这期教程中,用一个「虚构鬼屋房产表」当例子,完整演示了如何基于 Supabase 搭建一套按调用次数付费的API系统。抛开夸张的标题不谈,视频里真正有价值的是那些「把玩具和真正产品区分开来」的工程决策。本文梳理其核心思路。
商业模式:为什么数据表能变成收入来源
付费API的基本逻辑很直接:开发者注册后生成一个API密钥,然后按调用次数付费。作者举了一个常见定价——某个API每月一万次调用大约收费20美元。
视频里用的是「鬼屋房产」这种搞笑数据,但作者点明了关键:完全相同的模式适用于任何有价值的数据。把「鬼屋列表」换成「德克萨斯州带定价、销售历史和购买记录的真实房产数据」,对当地房产经纪人来说就是刚需,他们愿意为访问权限付费。
换句话说,数据本身的商业价值决定天花板,而API只是把数据变现的收费通道。这套通道搭得是否专业,决定了客户会不会长期留下来持续付费。
为什么不直接用 Supabase 自带的 API
Supabase 会自动为每个表生成 REST API,但作者明确指出它不适合这个场景。原因在于身份验证方式:Supabase 默认用 JWT,而 JWT 就像「音乐节的临时手环」,大约一小时就过期,是为浏览器或App里登录的用户设计的。
但API客户是开发者,他们会把密钥写进自己的代码,这个密钥需要持续工作好几个月。他们需要的是「永久的徽章」或「像纹身一样」的凭证,而不是按小时计费的手环。
由于 Supabase 没有内置这种长期密钥系统,作者选择自建。他给出的类比是「VIP夜店」:数据库是夜店,API密钥是VIP徽章,边缘函数则是门口刷徽章验证的保安。

JWT(JSON Web Token)是一种无状态的身份令牌,服务端无需查询数据库就能验证其有效性——这是它的优势,也是它的局限。JWT 通常在 payload 中内嵌过期时间(exp 字段),服务端解码后直接比对时间戳即可判断是否有效。正因为无需查库,撤销一个 JWT 几乎不可能:即便你删除了数据库里的用户记录,已签发的 JWT 在过期前依然有效。这对管理后台或移动 App 的登录场景影响有限(令牌一小时后自动失效),但对需要长期稳定、且能随时一键吊销的 API 密钥场景来说,这一特性是致命缺陷。自建基于哈希查询的密钥系统,每次请求都走一次数据库验证,换来的是「删除记录即撤销」的即时控制权,代价是多了一次数据库查询的延迟,但对安全敏感的付费 API 而言这是值得的取舍。
密钥系统三件套:绝不存储真实密钥
整套密钥系统遵循一条铁律:永远不要在任何地方存储真实的密钥。因为一旦数据库泄露而你存了明文密钥,所有客户的密钥都会一起泄露,甚至可能面临巨额赔偿。解决方案是只存储密钥的「指纹」。
第一部分:密钥表
创建一张 API 密钥表,最重要的列是 key_hash(密钥哈希)而非密钥本身。每个密钥通过 SHA256 处理生成单向指纹,无法反推回原始密钥。同时存储一个「前缀」(如 sk_live_L1A2B),用于在仪表板中让客户识别哪个密钥对应哪个用途——这正是 Stripe 等工具的做法,因为前缀不构成完整密钥,可以安全地明文存储。
最后用行级安全(RLS)锁定,策略核心是「认证 UID 必须等于用户 ID」,否则任何人都能列出所有人的密钥哈希。
第二部分:密钥生成器
密钥必须在数据库内部生成,绝不能在前端生成。因为浏览器生成的密钥要经过互联网传输才能保存,等于多了一个泄露环节。作者用 Postgres 函数实现:客户点击生成,函数创建随机字符串、进行哈希、只保存哈希值,并把真实密钥恰好一次显示在屏幕上。之后弹窗提示复制,「你再也看不到了」。

第三部分:守门员(边缘函数)
客户不能直接和数据库对话,请求全部发到 Supabase 托管的边缘函数。这个「门卫」在几毫秒内完成五件事:从请求头读取密钥、哈希处理、查询密钥表确认指纹存在、找出对应客户、返回属性数据。边缘函数使用 service role 密钥(绕过所有安全措施的高权限密钥),因此只能在服务端运行,绝不能出现在浏览器中。

作者在演示中验证了效果:用一串随机乱码当密钥请求,返回空数据;用真实认证用户生成的密钥请求「所有鬼屋」,则正确返回了 Haunted 为 true 的房产数据。RLS 在数据库层面拦截越权访问,删除一行密钥即等于「即时撤销」,下一次请求就会失败,无需额外代码。
边缘函数(Edge Functions)是部署在全球分布式节点上的轻量级无服务器函数,与传统服务器相比,它在地理位置上更靠近终端用户,从而降低网络延迟。Supabase 的边缘函数基于 Deno 运行时,每次请求冷启动时间通常在几十毫秒以内。在这套架构中,边缘函数承担了「应用层」的全部职责:它持有 service role 密钥(相当于数据库超级管理员凭证),能绕过行级安全策略直接操作数据,因此只能存在于受控的服务端环境,绝不能被打包进前端代码。这种设计模式本质上是「零信任架构」的简化版——公网永远只能看到边缘函数的入口,数据库本身对外完全不可见,攻击面被压缩到最小。
好的API设计:区分玩具和产品
作者强调,可用的密钥系统只是让人「能进门」,而好的API设计才让用户愿意留下来付费。黄金标准是:优秀的API让开发者无需阅读文档就能上手。
命名与HTTP方法
端点应该是名词的复数形式,比如 /properties 而不是 /getProperties。HTTP 方法本身已经表达了动作:GET 读取、POST 创建、PUT/PATCH 更新、DELETE 删除。所以 GET /properties 返回列表,GET /properties/42 返回单个房产,同一 URL 用 DELETE 方法则删除它。全程保持复数、保持命名风格一致即可。
诚实的状态码
状态码是告诉开发者「发生了什么」的关键:200 正常、201 已创建、401 密钥缺失或错误、404 资源不存在、429 触发速率限制、500 服务器出错。作者特别提醒:绝不要返回200却在响应体里藏错误,密钥无效就是401,没有商量余地。清晰的错误码是开发者选择继续用你的API、而不是流失的关键。
分页、过滤与版本控制
永远不要一次性返回全部数据。像谷歌搜索一样默认分页(如 page=2&limit=20),让筛选和排序在数据库端完成,只返回客户请求的部分。同时从第一天起就在路径中加入版本号(如 /v1/properties),这样日后重构数据时可以新建 /v2 而保留 /v1 运行,避免破坏性变更让成百上千开发者的工具同时崩溃。
API 版本控制中「破坏性变更」(Breaking Change)指的是任何会导致现有调用方代码失效的改动,常见形式包括:删除或重命名字段、修改字段数据类型、改变分页结构、调整错误码含义等。与之相对的「非破坏性变更」(如新增字段、新增端点)通常可以在同一版本内安全发布。从第一天就在路径中写入 /v1 的意义,不仅是为将来留退路,更是一种与客户的隐性契约:同一版本路径下的行为不会突然改变。Stripe 的 API 至今仍维护着多年前的旧版本,部分开发者的代码从未更新却依然正常工作——这种可靠性本身就是留存付费用户的核心竞争力之一。
把它锁起来:四道防护
密钥系统解决了「谁能进」,这一部分解决「进来后能干什么」。
速率限制:给每个密钥设上限,比如每分钟100次请求,超出就返回429。作者在边缘函数中演示了限流逻辑,并强调了一个关键陷阱——必须在用户层面而非密钥层面限制,否则用户只需不断创建新密钥就能绕过。合理的限额还能作为付费层级出售,比如免费每天10次、付费每月无限量。

防止篡改与SQL注入:限额等配置必须放在用户无法编辑的表中,否则用户可以直接在浏览器「检查元素」把限制改成1000万。同时永远不要用字符串拼接SQL,而应使用 Supabase 客户端内置方法,把输入当数据而非命令,并先验证「最低价格真的是数字吗」这类基本检查。
CORS 来源控制:像门口的访客名单,只允许你指定的网站从浏览器调用API。对公开只读数据可以放宽,但涉及登录会话或付费数据时必须严格,默认只开放必须开放的内容。
HTTPS 与最小权限:HTTP 像明信片,途中每个人都能看到密钥;HTTPS 是密封信封。Supabase 默认启用 HTTPS,规则是「永不关闭」。同时给每个密钥分配最小权限——service role 密钥只存在于边缘函数内,绝不出现在客户端。
文档即入门引导
最后一步是随产品发布文档。作者建议给客户提供像 Stripe、OpenAI 那样「复制粘贴即可成功」的示例——一条 curl 命令,带上端点、密钥请求头和一个看起来真实的密钥。开发者换上自己的密钥,10秒内看到数据返回,这个「第一次成功调用」就是激活时刻,越快达到越可能付费。作者把文档称为「入门引导」,因为它本质上就是。
小结
这期教程的价值不在于「月入百万」的营销话术,而在于它把一套生产级付费API应该具备的工程决策讲清楚了:密钥只存哈希、生成在服务端、访问走边缘函数、RLS做数据隔离,再加上命名规范、状态码、分页、版本控制、速率限制、防注入、CORS 和 HTTPS 这些细节。对想把自己手里数据变现的独立开发者来说,这是一份可直接照着落地的清单。
相关推荐

气态巨行星上的浮空城市:为什么人类终将移居木星云端
SFIA 主持人 Isaac Arthur 重新定义气态巨行星浮空城市:它们不是等待聚变的燃料站,而是散装氢、氦、氮的"质量城市"。本文解析其工程原理、供电方案与从工业前哨到文明家园的演化逻辑。

用Claude Code一天半做出AI测验:Vibe Coding的真实样本
一位开发者用Claude Code结合Opus 5.5与Fable 5.1,在一天半内做出一款PS1复古风格的AI主题测验游戏。本文解析这个业余项目背后的AI辅助编程实践与行业启示。

用Claude+Muse打造自动化膳食规划:AI如何替代HelloFresh
一位不懂编程的Reddit用户用Claude和Muse搭建了自动化膳食规划系统,涵盖菜单规划、沃尔玛自动下单、厨房平板界面,号称HelloFresh杀手。本文解析其工作流与AI生活自动化的启示。