jqzindie · ai
POST

用 Supabase 做只读数据站:publishable key、RLS、安全边界与常见坑

2026-02-08jqzdev.com

English TL;DR: A “read-only” Supabase setup still needs proper RLS and table boundaries. Use publishable keys only with strict policies; keep write paths server-side.

独立开发做数据站/工具站时,Supabase 很顺手:

  • Postgres + 管理台
  • REST/Realtime/SDK
  • 部署成本低

但也很容易踩坑:

  • “反正是只读” → 直接开放表
  • publishable key 泄露后,被人把你的配额刷爆
  • RLS 写错,一不小心把敏感字段放出去

这篇讲清楚一个核心问题:

你到底应该开放什么?不应该开放什么?


1) publishable key 是什么:它不是“秘密”,它是“能力门票”

Supabase 的 publishable key(匿名 key)本质是:

  • 客户端可以带着它访问你的 Supabase
  • 访问权限由 RLS(Row Level Security) 决定

所以 publishable key 泄露并不稀奇(它本来就会在前端里)。 真正决定安全性的,是:

  • RLS 是否严格
  • 表结构是否合理
  • 是否把写入/敏感查询留在服务端

2) 只读数据站的推荐边界(最小可行)

把系统拆成三层:

  1. 采集/计算层(你的服务器)

    • 抓数据
    • 清洗
    • 写入数据库
  2. 数据服务层(Supabase Postgres)

    • 存储结果
    • 通过 View / Materialized View 输出“可公开消费”的表
  3. 展示层(Next.js / Vercel)

    • 仅做查询 + 展示

最关键的一条:

不要让前端直接查询“原始表”。

原始表通常包含:

  • 内部字段
  • 供应商 id
  • 采集状态
  • 失败信息

这些都不适合公开。


3) 推荐做法:用 View 暴露“public shape”

例如:

  • raw_funding_rates(内部表)
  • public_funding_rates(view)

public_* 的字段应当:

  • 只包含你愿意公开的列
  • 不包含任何内部 id/token/provider 字段
  • 尽量规范化:单位、精度、时间戳

然后 RLS 只对 public_* 生效(或者你直接只允许访问 view 相关 schema)。


4) RLS(Row Level Security)怎么写才不会翻车

如果你的数据是完全公开的(比如行情/费率),你依然建议:

  • 开启 RLS
  • 明确写出允许 select 的 policy

例子(思路示意):

  • 允许所有人 select
  • 禁止所有人 insert/update/delete

这样就算有人拿到 publishable key,也只能读你允许的那部分。


5) 三个最常见坑

坑 1:忘了开启 RLS

你以为写了 policy,但如果没开启 RLS,policy 根本不生效。

坑 2:把 write path 放在客户端

比如:

  • 用户提交表单直接写库
  • 客户端直接调用 insert

这会让你非常难做风控(限流、反刷、审计)。

正确做法:

  • 写入走 Next.js Route Handler(服务端)
  • 或者走你自己的采集服务

坑 3:把敏感表 join 到 public view

只要 public view 最终能被 select,它 join 出来的字段就可能被推断/泄露。


6) 你应该怎么“验证只读真的只读”

最小验证:

  1. 用 publishable key 在浏览器里尝试 select(成功)
  2. 尝试 insert/update/delete(必须失败)
  3. 尝试访问原始表(必须失败)

如果你愿意再加一层:

  • 对外查询统一走 RPC(SQL function)
  • 限制参数范围

这样更好控,但会牺牲一些开发效率。


7) 什么时候该用 service role key?

结论非常简单:

  • 只要是写入/敏感读取 → service role key 只能在服务端
  • 永远不要把 service role key 放到前端

如果你正在做类似 PerpHQ 这种数据站:

  • 前端只读 + publishable key + 严格 RLS
  • 写入/计算放到采集服务
  • public view 输出你想让外部看到的数据形状

这是长期最省心、也最稳的一套。

RELATED