Skip to content

建立 2026-09-14 更新 2026-09-14

API Keys

每個打到 Supabase 的請求都帶一把 API key。它回答的是「什麼程式在連線」(網頁、App、伺服器),不是「哪一位使用者」。使用者身分另外由 Auth 的 JWT 處理。

選錯金鑰,輕則 RLS 擋下所有查詢,重則整庫被讀走。

該用哪一把

問自己:這段程式會不會被使用者拿到?

程式跑在哪 用這把 key 原因
瀏覽器、手機 App、公開 CLI Publishable keysb_publishable_... 一定會被看到,只能碰到 RLS 允許的資料
你控制的伺服器、Edge Function、cron Secret keysb_secret_... 略過 RLS,絕不能離開伺服器

官方預計在 2026 年底淘汰舊的 anonservice_role JWT 金鑰。新金鑰是短字串,不是以 eyJ 開頭的長 JWT。若教學或 AI 叫你貼一長串 eyJ...,那是舊寫法。

# 前端可公開。變數前綴依框架而定(Vite 用 VITE_,Next.js 用 NEXT_PUBLIC_)。
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...

# 只給伺服器。不要加會被打包進前端的前綴。
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SECRET_KEY=sb_secret_...

金鑰本身不要寫進 git。用 .env,並把 .env 加進 .gitignore

金鑰對應的 Postgres 角色

Client 用 publishable key 連線時,資料庫角色取決於使用者有沒有登入:

Key 使用者已登入 Postgres 角色
Publishable anon
Publishable authenticated
Secret 不適用 service_roleBYPASSRLS

RLS 政策 是寫給 anonauthenticated 看的。Secret key 對應的 service_role 會跳過所有政策,所以它等於資料庫管理員。

在程式裡使用

前端:

import { createClient } from '@supabase/supabase-js'

export const supabase = createClient(
  import.meta.env.VITE_SUPABASE_URL,
  import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY
)

後端才用 secret key。官方也會擋:把 secret key 從瀏覽器送出,平台會回 401

import { createClient } from '@supabase/supabase-js'

export const supabaseAdmin = createClient(
  process.env.SUPABASE_URL,
  process.env.SUPABASE_SECRET_KEY
)

常見誤解

  • 把 publishable key 藏起來就安全:做不到。建置後的 JS 一定看得到。安全靠 RLS。
  • 前端用 secret key 比較方便:等於關掉所有列級權限,任何訪客都能讀寫整庫。
  • 沒開 RLS 的表只給「自己的 App」用:任何人都能用你的 URL + publishable key 打 REST API。

金鑰外洩時:先修好外洩原因,再在 Dashboard 的 Settings → API Keys 建立新 secret key、換成新值,最後刪除舊的。不要先刪再改程式,否則線上會全面斷線。

相關資料