Skip to content
Getting Started

API 密钥

每个对你 Supabase 项目的请求都带有一个 API 密钥。这个密钥用来识别是谁在调用你的项目:网页、移动应用、服务器,还是 Edge Function。Supabase Auth 会在有人登录时识别是谁在调用。

🌐 Every request to your Supabase project carries an API key. The key identifies what is calling your project: a web page, a mobile app, a server, or an Edge Function. Supabase Auth identifies who is calling, when someone is signed in.

本指南涵盖内容:

🌐 This guide covers:

你用哪个键? #

🌐 Which key do you use?

通过问代码在哪里运行来选择密钥。

🌐 Pick the key by asking where the code runs.

代码运行的地方使用这个密钥为什么
你发布的任何东西:浏览器、移动应用、命令行工具、脚本可发布密钥任何人都可以读取,但只能访问行级安全允许的内容
你控制的任何东西:服务器、Edge 函数、定时任务私密密钥它可以绕过行级安全,所以绝不能脱离你的控制

把你项目的数据想象成一栋架构。可发布的密钥贴在前门上,它只开大堂。秘密密钥是万能密钥,放在你口袋里。

🌐 Think of your project's data as a building. The publishable key is taped to the front door, and it only opens the lobby. The secret key is the master key, and it stays in your pocket.

在你知道需要哪个密钥后,查看 查找和使用你的密钥 来获取其值并接入。如果要在已经使用旧密钥的应用中更换密钥,则请改为参考 迁移到新 API 密钥。

🌐 After you know which key you need, see Find and use your keys to get its value and wire it in. To swap keys in an application that already ships legacy keys, follow Migrating to new API keys instead.

API 密钥是如何工作的 #

🌐 How API keys work

API 密钥能够识别什么 #

🌐 What an API key identifies

API 密钥用于验证应用组件,从而让它访问 Supabase 服务。应用组件可以是网页、移动应用或者服务器。API 密钥并不区分用户,而是区分应用。

🌐 An API key authenticates an application component to give it access to Supabase services. An application component might be a web page, a mobile app, or a server. An API key doesn't distinguish between users but between applications.

API 密钥提供了数据访问的第一层身份验证。Supabase Auth 是在此基础上构建的。下表说明了它们的区别:

🌐 API keys provide the first layer of authentication for data access. Supabase Auth builds on top of that. This table covers the difference:

责任问题回答
API 密钥是什么在访问该项目?一个网页、一个移动应用、一个服务器,或者一个 Edge 函数
Supabase Auth谁在访问该项目?一个已登录的用户

密钥类型 #

🌐 Key types

Supabase 支持四种类型的 API 密钥:

🌐 Supabase supports four types of API keys:

类型格式权限可用性用途
可发布密钥sb_publishable_...低平台, 命令行接口可以安全公开:网页、移动或桌面应用、GitHub Actions、命令行工具、源代码。
秘密密钥sb_secret_...提升平台,CLI仅在应用的后端组件中使用,例如服务器、带有自身授权检查的 API、Edge Functions 和微服务。它们提供对项目数据的完全访问权限,绕过 行级安全。
anonJWT(长寿命)低平台, 命令行工具可发布密钥的旧版本。
service_roleJWT(长时间有效)升高的平台,命令行接口旧版本的密钥。

可公开的密钥和秘密密钥都是短字符串,不是 JWT。如果某个工具、教程或 AI 助手告诉你去复制一个以 eyJ 开头的长密钥,那说明它是为旧版密钥写的。

🌐 Publishable and secret keys are short strings, not JWTs. If a tool, tutorial, or AI assistant tells you to copy a long key that begins with eyJ, it was written for the legacy keys.

运行 supabase start 会打印出你本地项目的可发布密钥和秘密密钥。本地秘密密钥取代本地的 service_role 密钥。查看 CLI 入门指南 获取完整输出。

🌐 Running supabase start prints a publishable key and a secret key for your local project. The local secret key takes the place of the local service_role key. See the CLI getting started guide for the full output.

旧版 anon 和 service_role#

🌐 Legacy anon and service_role keys

创建可发布和秘密密钥不会撤销你的旧密钥。这两种密钥系统可以同时使用。

🌐 Creating publishable and secret keys doesn't revoke your legacy keys. Both key systems work at the same time.

创建可发布或私密密钥会将其添加到你现有的 anon 和 service_role 密钥旁边,而不会影响它们,因此你的旧密钥仍然可以继续使用。它们会一直有效,直到你在仪表板的 设置 > API 密钥 部分禁用它们,这需要单独操作。

🌐 Creating a publishable or secret key adds it alongside your existing anon and service_role keys without affecting them, so your legacy keys keep working. They stay valid until you disable them in the Settings > API Keys section of the Dashboard, which is a separate step.

查看 迁移到新 API 密钥 了解完整流程。

🌐 See Migrating to new API keys for the full process.

可发布的密钥和公共组件 #

🌐 Publishable keys and public components

可发布的密钥用于识别你应用的公共部分。公共部分运行在无法保密的环境中,包括:

🌐 Publishable keys identify the public components of your application. Public components run in environments where you can't keep a secret. These include:

  • 网页,密钥被打包在源代码里。
  • 移动端或桌面应用,其中密钥被打包在已编译的包或可执行文件中。
  • 命令行接口、脚本、工具或其他预先构建的可执行文件。
  • 公开 API 会直接返回密钥,无需先授权。

这些环境总是被认为是公开的,因为任何人都可以从源代码或构建产物中获取密钥。

🌐 These environments are always considered public because anyone can retrieve the key from the source code or build artifacts.

Postgres 角色和行级安全 #

🌐 Postgres roles and Row Level Security

每个密钥对应一个内置的 Postgres 角色,而你的行级安全策略就是基于这个角色匹配的。使用可发布密钥并不意味着你的用户是匿名的:你的应用使用可发布密钥进行认证,而你的用户则通过 Supabase Auth 使用他们自己的 JWT 分别进行认证。

🌐 Every key resolves to a built-in Postgres role, and that role is what your Row Level Security policies match on. Using a publishable key doesn't mean your user is anonymous: your application authenticates with the publishable key while your user authenticates separately through Supabase Auth with their own JWT.

键用户是否通过 Supabase Auth 登录Postgres 角色
可发布密钥否anon
可发布密钥是authenticated
密钥不适用service_role

为 anon 和 authenticated 角色编写行级安全策略。策略永远不会应用于密钥,因为 service_role 有 BYPASSRLS 属性。

🌐 Write your Row Level Security policies for the anon and authenticated roles. Policies never apply to a secret key, because service_role has the BYPASSRLS attribute.

Postgres 会先评估表的授权,然后才应用行级安全。两种失败的情况看起来不同。缺少授权会返回权限错误,包括 service_role 的情况,而匹配不到任何行的策略会返回空结果。在调试策略之前先检查授权。参见 保护你的 API。

🌐 Postgres evaluates table grants first, and only then applies Row Level Security. The two failures look different. A missing grant returns a permission error, including for service_role, whereas a policy that matches no rows returns an empty result. Check the grant before you debug the policy. See Securing your API.

秘密密钥和高级权限 #

🌐 Secret keys and elevated access

与可发布的密钥不同,秘密密钥允许对你的项目数据进行更高级的访问。只在安全的、开发者控制的应用组件中使用它们,例如:

🌐 Unlike publishable keys, secret keys allow elevated access to your project's data. Use them only in secure, developer-controlled components of your application, such as:

  • 运行自己授权检查的服务器,比如 Edge Functions、微服务和网页服务器。
  • 周期性任务、队列处理器、主题订阅者。
  • 先运行授权检查的管理和后台工具。
  • 数据处理流程,比如用于分析、报表、备份或数据库同步。

密钥可以通过内置的 service_role Postgres 角色授权访问你项目的数据。按照设计,这个角色对你项目的数据拥有完全访问权限。它还有 BYPASSRLS 属性,所以它会跳过你设置的每一条行级安全策略。

🌐 Secret keys authorize access to your project's data through the built-in service_role Postgres role. By design, this role has full access to your project's data. It also has the BYPASSRLS attribute, so it skips every Row Level Security policy you attach.

秘密密钥比旧的基于 JWT 的 service_role 密钥更优秀,我们推荐尽可能使用它们。它们增加了防止滥用的检查:

🌐 Secret keys improve on the old JWT-based service_role key, and we recommend them wherever possible. They add checks that prevent misuse:

  • 秘密密钥在浏览器里不管用。Supabase 会根据 User-Agent 头来匹配,然后返回 HTTP 401 未授权。
  • 如果没有东西使用它们,一个项目就不需要任何密钥。

找并使用你的密钥 #

🌐 Find and use your keys

将密钥放入应用有两个步骤。你需要先复制这个值,这需要登录过的 Dashboard 会话,然后你的代码通过名字读取它。密钥本身从不属于源代码,所以先在 .env 里设置这些名字:

🌐 Getting a key into an app has two halves. You copy the value, which needs a signed-in Dashboard session, and your code reads it by name. The key itself never belongs in source code, so start by setting these names in .env:

# Safe to expose to the browser. Prefix per your framework.
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...
# Server-only. Never prefix these, or your bundler will ship the key.
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SECRET_KEY=sb_secret_...

找你的密钥 #

🌐 Find your keys

选择与你工作地点相符的路径。

🌐 Pick the path that matches where you are working.

下面的每个路径都会读取已经存在的密钥。如果你的项目还没有可发布的或秘密密钥,请先在仪表板的 设置 > API 密钥 部分创建它们。

🌐 Every path below reads keys that already exist. If your project has no publishable or secret key yet, create them first in the Settings > API Keys section of the Dashboard.

在手动设置项目时使用仪表板。它只需要一个已登录的会话。

🌐 Use the Dashboard when you are setting up a project by hand. It needs nothing but a signed-in session.

  1. 打开你项目的连接对话框。它会显示你选择的框架对应的 URL 和可发布密钥,准备好粘贴到 .env。
  2. 如果你想选择某个特定的密钥,或者查看项目中的所有密钥,请改为打开仪表板的 设置 > API 密钥 部分。每个密钥都在那里,不管是不是旧的,而且没有单独的 设置 > API 页面。
  3. 把每个值复制到上面变量名下的 .env。

在客户端代码中使用可发布的密钥 #

🌐 Use a publishable key in client code

在任何传到用户设备的代码中,把可发布密钥传给 createClient。

🌐 Pass the publishable key to createClient in any code that reaches a user's device.

import { createClient } from '@supabase/supabase-js'
export const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!
)

行级安全控制决定这个客户端可以访问什么,所以在部署前在每张表上启用它。

🌐 Row Level Security decides what this client can reach, so enable it on every table before you deploy.

在后端代码中使用一个密钥 #

🌐 Use a secret key in backend code

只有在不会到达用户设备的代码中(比如服务器路由或工作线程)才把密钥传给 createClient。

🌐 Pass the secret key to createClient only in code that never reaches a user's device, such as a server route or a worker.

import { createClient } from '@supabase/supabase-js'
export const supabaseAdmin = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SECRET_KEY!
)

在边缘函数内部 #

🌐 Inside an Edge Function

不要在 Edge Function 中从环境读取密钥。改用 @supabase/server SDK。它会帮你验证调用者的密钥,并在 ctx 上返回一个特权客户端,这样密钥就不会出现在你的代码里。

🌐 Don't read the key from the environment inside an Edge Function. Use the @supabase/server SDK instead. It verifies the caller's secret key for you and hands back a privileged client on ctx, so the key never appears in your code.

import { withSupabase } from 'npm:@supabase/server@1'
export default {
fetch: withSupabase({ auth: 'secret' }, async (_req, ctx) => {
// ctx.supabaseAdmin bypasses Row Level Security
const { data } = await ctx.supabaseAdmin.from('profiles').select('email')
return Response.json({ data })
}),
}

为使用密钥而不是用户令牌调用的函数设置 verify_jwt = false。

🌐 Set verify_jwt = false for a function called with a secret key rather than a user's token.

[functions.roster]
verify_jwt = false

如果你自己构建客户端而不是使用 SDK,就从 SUPABASE_SECRET_KEYS 读取密钥。运行时会以 JSON 字典的形式注入,字典的键是密钥名称,所以选你想要的那个就行。

🌐 If you build the client yourself instead of using the SDK, read the key from SUPABASE_SECRET_KEYS. The runtime injects it as a JSON dictionary keyed by key name, so pick the one you want.

import { createClient } from 'npm:@supabase/supabase-js@2'
const secretKeys = JSON.parse(Deno.env.get('SUPABASE_SECRET_KEYS')!)
const supabaseAdmin = createClient(Deno.env.get('SUPABASE_URL')!, secretKeys['default'])

SUPABASE_ANON_KEY 和 SUPABASE_SERVICE_ROLE_KEY 仍然存在于运行时中,但它们携带旧的键,所以读取它们会让你继续使用已弃用的方式。查看 环境变量 获取完整的注入变量列表。

如果你是在现有应用中替换旧密钥,而不是重新开始,请按照 迁移到新 API 密钥 操作。

🌐 If you are replacing legacy keys in an existing application rather than starting fresh, follow Migrating to new API keys.

更换泄露或受损的密钥 #

🌐 Rotate a leaked or compromised key [#leaked-key]

这个程序涵盖了泄露的密钥和泄露的 service_role 密钥。

🌐 This procedure covers both a leaked secret key and a leaked service_role key.

别急。在旋转任何东西之前,先修复泄漏的根本原因。OWASP 风险评级方法可以帮助你判断事件的严重性,并规划下一步行动。

🌐 Don't rush. Fix the root cause of the leak before you rotate anything. The OWASP Risk Rating Methodology helps you judge the severity of the incident and plan your next steps.

  1. 在仪表板的 设置 > API 密钥 部分创建一个新的秘密密钥。
  2. 用新的密钥替换应用中使用的所有被泄露的密钥。如果被泄露的密钥是基于 JWT 的 service_role 密钥,就用新的秘密密钥替换它。
  3. 确认每个组件现在都使用新的密钥。
  4. 废弃被泄露的密钥。删除一个秘密密钥是不可撤销的,所以在完成步骤3之前不要开始。如果是旧版的 anon 或 service_role 密钥,请在同一仪表板部分停用旧密钥。停用是可逆的,所以如果发现遗漏的客户端,可以重新启用它们。

安全参考 #

🌐 Security reference

可发布密钥不能防护的东西 #

🌐 What publishable keys don't protect against

可发布的密钥并不是为了防护以下情况,因为任何人都可以从公开组件中获取密钥:

🌐 Publishable keys aren't intended to protect against the following, because anyone can retrieve a key from a public component:

  • 静态或动态代码分析以及逆向工程尝试。
  • 在浏览器中使用网络检查器。
  • 跨站请求伪造、跨站脚本攻击、网络钓鱼攻击。
  • 中间人攻击

当你使用可发布的密钥时,Postgres 会通过内置的 anon 和 authenticated 角色来保护你项目的数据访问。为了完全保护,请确认:

🌐 When you use a publishable key, Postgres guards access to your project's data through the built-in anon and authenticated roles. For full protection, confirm that:

  • 你已经在所有表上启用了行级安全。
  • 你会定期检查分行级别安全策略,对 anon 和 authenticated 角色授予的权限进行审查。
  • 在不了解改变会带来什么影响之前,你不要随意更改角色的属性。

你项目的安全顾问会检查内置 Postgres 角色的常见安全问题。在你忽略任何发现之前,请仔细查看每一条建议。

🌐 Your project's Security Advisor checks for common security problems with the built-in Postgres roles. Review each finding carefully before you dismiss it.

安全处理密钥 #

🌐 Handling secret keys safely

泄露秘密密钥会让你项目里的所有数据面临风险。下面的规则按它们可以防止的错误类型分组整理。

🌐 Exposing a secret key puts all of your project's data at risk. The rules below are grouped by the kind of mistake they prevent.

秘密密钥绝不应出现的地方

  • 一个网页、公共文档、源代码,或者打包好的移动端、桌面端或命令行工具包。
  • 一个浏览器,即使在 localhost 上。

秘密密钥绝不应该如何传输

  • 通过聊天、电子邮件或短信。
  • 在 URL 或查询参数中,因为这些经常会被记录。
  • 在请求头中,直到你有日志清理措施为止。
  • 通过普通 HTTP,或者连接到你项目的 Supabase 端点以外的任何主机。

绝对不能写下来的东西

  • 不要记录密钥,即使看起来无效。今天的一个打字错误可能会在以后暴露真正的密钥。
  • 如果你必须记录一个密钥,前缀之后的随机部分不要记录超过6个字符。
  • 为了记录哪个键被使用了,改为存储它的 SHA256 哈希值。

存储和共享密钥

  • 只在你完全拥有或控制的电脑上使用密钥。
  • 加密存储在文件或环境变量中的密钥。
  • 不要把密钥放入源码管理,包括 CI 脚本。改用工具自带的密钥存储。
  • 通过加密传输工具分享密钥,比如你密码管理器里的工具。更好的方法是,让对方从仪表板的 设置 > API 密钥 部分读取密钥。

限制泄漏造成的损害

  • 每个后端组件都用单独的密钥。如果其中一个组件泄露了密钥,你只需要更换那个组件的密钥。
  • 立即删除泄露的密钥。浏览器阻止会返回 HTTP 401 未授权,但攻击者仍然可以从其他工具使用这个密钥。

使用安全编码规范处理密钥。

🌐 Handle secret keys using secure coding practices.

已知限制 #

🌐 Known limitations

可公开和秘密密钥不是 JWT,这会带来一些需要注意的兼容性差异:

🌐 Publishable and secret keys aren't JWTs, which creates a few compatibility differences to plan for:

  • 把可发布和秘密密钥放在 apikey 头里,而不是 Authorization: Bearer。因为这些密钥不是 JWT,任何试图把它们当作 JWT 验证的操作都会失败。为了迁移兼容,verify_jwt 平台检查接受它们放在任一头里,但通过该检查并不表示调用者已被认证。参见 授权头。
  • Edge Functions 需要在代码中授权 API 密钥。仅靠 verify_jwt 检查无法验证只发送 API 密钥的调用者。使用 @supabase/server SDK,就像在 保护 Edge Functions 中展示的那样,而不是依赖平台检查。
  • 公共实时连接最长持续 24 小时,除非通过 Supabase Auth 或支持的第三方认证提供者将连接升级为用户级别认证。