Supabase RLS 是 AI 寫完網站後,我會要求一定檢查的地方。登入畫面做出來,不代表資料已經隔離。會員 A 看不到管理按鈕,也不代表他不能直接呼叫 API 讀取會員 B 的資料。前端只是介面,權限必須在後端與資料庫落實。
還不熟這套工具,先看Supabase 與 Vibe Coding 入門。這篇專注在「每個會員只能讀自己的資料」這個情境,不是完整的多租戶或法規合規方案。
RLS 管資料列,登入和授權不是同一件事
RLS 是 Row Level Security,也就是逐列存取規則。登入先證明你是誰;資料表的 grants 決定角色能做哪些操作;RLS 再篩選角色能接觸哪些資料列。這三層不能互相取代。會員登入成功後,仍需要適當的規則。
中央社 2026 年 9 月 10 日的戴爾調查報導指出,56% 企業將安全、合規與隱私列為擴大 AI 應用的主要限制因素。這個數字不能解讀為 Supabase 的漏洞比例;它提醒的是,AI 應用上線後仍有資料治理責任。閱讀調查來源。
範例:會員只能讀取自己的筆記
以下只適合在空白測試專案的 SQL Editor 練習,請勿直接套到既有資料表。先建立示範表,再限制公開角色,最後給已登入會員讀取自己資料的規則。此範例刻意只提供讀取,不包含新增、更新與刪除。
create table public.member_notes_demo (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references auth.users(id),
body text not null
);
alter table public.member_notes_demo enable row level security;
revoke all on public.member_notes_demo from anon, authenticated;
grant select on public.member_notes_demo to authenticated;
create policy "read_own_notes_demo"
on public.member_notes_demo for select
to authenticated
using ((select auth.uid()) = user_id);
user_id 要對應真正的使用者 ID,不能只拿表單傳來的電子郵件當憑據。新增資料若由伺服器處理,也必須由可信任的使用者驗證結果決定歸屬。不要讓瀏覽器隨意指定任意會員的 user_id。
新增、修改、刪除要各自設計
要讓會員新增資料,需要 INSERT 權限與對應的 WITH CHECK 規則。修改則要一起考慮原本能碰哪筆資料,以及修改後是否仍屬於自己。刪除也要另外評估。不要為了讓畫面不報錯,就加上一條所有人都能操作所有資料的規則。
複雜專案還有團隊、公司與管理者角色。同一家公司能不能共享資料?離職後是否立即失去權限?這些應先寫成權限表,再交給 AI 產生政策,不能全部塞進一條「有登入就放行」。
公開金鑰不等於管理金鑰
| 項目 | 使用位置 | 注意事項 |
|---|---|---|
| Publishable key | 公開客戶端 | 配合使用者登入、grants 與 RLS |
| Secret key | 受控伺服器 | 具有高權限,不能放進網頁 |
| 舊版 service_role key | 受控伺服器 | 不能作為前端解決 RLS 錯誤的方法 |
前端環境變數即使存在 .env,只要打包進 JavaScript,就可能被取得。變數名稱寫成 SECRET 也不會自動變安全。若高權限金鑰已經外流,應更換並檢查存取紀錄,而不是只把它從畫面刪掉。
用三個身分測試,不能只看 SQL Editor
- 未登入訪客:讀不到會員私有資料。
- 會員 A:能看到自己的資料,看不到 B 的資料。
- 會員 B:同樣不能讀到 A 的資料。
- 直接改請求參數:換成另一個 user_id 仍不能越權。
- 伺服器管理流程:自己完成身分與角色檢查,不相信前端傳來的管理者旗標。
SQL Editor 可能使用較高權限執行,裡面看得到資料不能證明一般會員也被正確限制。請用一般客戶端與實際登入身分驗證。RLS 之外,Storage、函式與伺服器 API 也有各自的存取邊界;通過一張表的測試,不代表全站安全。
你可以要求 AI 把允許與拒絕的測試都列出,再用Playwright 驗證介面流程,搭配 API 層的越權測試。準備把原型變成企業網站時,可預約 AI 工作流程與網站導入諮詢。










