Skip to content
Auth

为 SSR 创建 Supabase 客户端

Configure your Supabase client to use cookies

要在 Supabase 中使用服务端渲染(SSR),你需要配置 Supabase 客户端使用 cookies。@supabase/ssr 包可以帮你在 JavaScript/TypeScript 应用中做到这一点。

🌐 To use Server-Side Rendering (SSR) with Supabase, you need to configure your Supabase client to use cookies. The @supabase/ssr package helps you do this for JavaScript/TypeScript applications.

安装 #

🌐 Install

安装 @supabase/supabase-js@supabase/ssr 辅助包:

🌐 Install the @supabase/supabase-js and @supabase/ssr helper packages:

1
npm install @supabase/supabase-js @supabase/ssr

设置环境变量 #

🌐 Set environment variables

在项目根目录下创建一个 .env.local 文件。在文件中,设置项目的 Supabase URL 和 Key:

🌐 Create a .env.local file in the project root directory. In the file, set the project's Supabase URL and Key:

获取 API 详情 #

🌐 Get API details

要与数据库表中的数据进行交互,你可以使用封装了自动生成的数据 API 端点的客户端库,并使用来自项目 Connect 对话框的项目 URL 和密钥进行认证。

🌐 To interact with data in database tables, you use the client libraries that wrap the auto-generated Data API endpoints, authenticating using the Project URL and key from the project Connect dialog.

Project URL
Publishable key
1
NEXT_PUBLIC_SUPABASE_URL=supabase_project_url
2
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=supabase_publishable_key

创建一个客户 #

🌐 Create a client

你需要一些设置代码来配置 Supabase 客户端以使用 Cookie。一旦你有了这些工具代码,你就可以使用 createClient 工具函数来获取一个配置好的 Supabase 客户端。

🌐 You need setup code to configure a Supabase client to use cookies. Once you have the utility code, you can use the createClient utility functions to get a properly configured Supabase client.

在浏览器上运行的代码里用浏览器客户端,在服务器上运行的代码里用服务器客户端。

🌐 Use the browser client in code that runs on the browser, and the server client in code that runs on the server.

Supabase Auth SDK 包含三种不同的函数,用于验证用户对应用的访问权限:

🌐 The Supabase Auth SDK contains three different functions for authenticating user access to applications:

方法总结 #

🌐 Summary of the methods

  • 使用 getClaims 来保护页面和用户数据。它会从存储中读取访问令牌并进行验证。在本地通过 WebCrypto API 和缓存的 JWKS 端点进行操作,当项目使用非对称签名密钥时(这是新项目的默认设置);如果使用对称密钥,则仅通过调用 getUser 来验证。返回的声明总是来自解析 JWT,而不是通过用户查询获得。
  • [getUser](/docs/reference/javascript/auth-getuser) 会向项目的 Auth 实例发起网络请求以获取用户记录,这样可以获得用户的最新信息,但需要进行一次网络请求。
  • getSession 当你需要原始会话(访问令牌、刷新令牌和过期时间)时使用。例如,将访问令牌转发到另一个服务。会话是直接从本地存储加载的,并不会重新向认证服务器验证,因此当存储与客户端共享(如 cookies、请求头)时,嵌入的用户对象不应单独信任。要验证身份,请使用 getClaims 验证访问令牌,或调用 getUser 获取一个新的、服务器确认的用户记录。

总结:使用 getClaims 来验证身份(通常用于保护页面和数据),当你需要从认证服务器获取最新的用户记录时用 getUser,而当你直接需要访问或刷新令牌时用 getSession,但不要依赖它返回的用户对象来做授权决策。

编写实用函数来创建 Supabase 客户端 #

🌐 Write utility functions to create Supabase clients

要从 Next.js 应用访问 Supabase,你需要两种类型的 Supabase 客户端:

🌐 To access Supabase from a Next.js app, you need 2 types of Supabase clients:

  1. 客户端组件 client - 用于从在浏览器中运行的客户端组件访问 Supabase。
  2. 服务器组件客户端 - 用于从仅在服务器上运行的服务器组件、服务器操作和路由处理程序中访问 Supabase。

由于 Next.js 服务器组件不能写入 cookie,你需要一个 代理 来刷新过期的认证令牌并存储它们。

🌐 Since Next.js Server Components can't write cookies, you need a Proxy to refresh expired Auth tokens and store them.

代理负责:

🌐 The Proxy is responsible for:

  1. 通过调用 supabase.auth.getClaims() 刷新认证令牌。
  2. 将刷新后的认证令牌传递给服务器组件,这样它们就不会自己尝试刷新同一个令牌。这可以通过 request.cookies.set 来实现。
  3. 将更新后的认证令牌传递给浏览器,以替换旧的令牌。这是用 response.cookies.set 完成的。

Supabase Auth SDK 包含三种不同的函数,用于验证用户对应用的访问权限:

🌐 The Supabase Auth SDK contains three different functions for authenticating user access to applications:

方法总结 #

🌐 Summary of the methods

  • 使用 getClaims 来保护页面和用户数据。它会从存储中读取访问令牌并进行验证。在本地通过 WebCrypto API 和缓存的 JWKS 端点进行操作,当项目使用非对称签名密钥时(这是新项目的默认设置);如果使用对称密钥,则仅通过调用 getUser 来验证。返回的声明总是来自解析 JWT,而不是通过用户查询获得。
  • [getUser](/docs/reference/javascript/auth-getuser) 会向项目的 Auth 实例发起网络请求以获取用户记录,这样可以获得用户的最新信息,但需要进行一次网络请求。
  • getSession 当你需要原始会话(访问令牌、刷新令牌和过期时间)时使用。例如,将访问令牌转发到另一个服务。会话是直接从本地存储加载的,并不会重新向认证服务器验证,因此当存储与客户端共享(如 cookies、请求头)时,嵌入的用户对象不应单独信任。要验证身份,请使用 getClaims 验证访问令牌,或调用 getUser 获取一个新的、服务器确认的用户记录。

总结:使用 getClaims 来验证身份(通常用于保护页面和数据),当你需要从认证服务器获取最新的用户记录时用 getUser,而当你直接需要访问或刷新令牌时用 getSession,但不要依赖它返回的用户对象来做授权决策。

在你的项目根目录下创建一个 lib/supabase 文件夹,或者如果你正在使用 ./src 文件夹,就在里面创建,每种客户端类型都放一个文件。然后复制每种客户端类型的 lib 工具函数。

🌐 Create a lib/supabase folder at the root of your project, or inside the ./src folder if you are using one, with a file for each type of client. Then copy the lib utility functions for each client type.

1
import { createBrowserClient } from '@supabase/ssr'
2
3
export function createClient() {
4
return createBrowserClient(
5
process.env.NEXT_PUBLIC_SUPABASE_URL!,
6
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!
7
)
8
}
View source

连接代理 #

🌐 Hook up proxy

这段代码添加了一个 matcher,这样 Proxy 就不会在不访问 Supabase 的路由上运行。

🌐 The code adds a matcher so the Proxy doesn't run on routes that don't access Supabase.

Supabase Auth SDK 包含三种不同的函数,用于验证用户对应用的访问权限:

🌐 The Supabase Auth SDK contains three different functions for authenticating user access to applications:

方法总结 #

🌐 Summary of the methods

  • 使用 getClaims 来保护页面和用户数据。它会从存储中读取访问令牌并进行验证。在本地通过 WebCrypto API 和缓存的 JWKS 端点进行操作,当项目使用非对称签名密钥时(这是新项目的默认设置);如果使用对称密钥,则仅通过调用 getUser 来验证。返回的声明总是来自解析 JWT,而不是通过用户查询获得。
  • [getUser](/docs/reference/javascript/auth-getuser) 会向项目的 Auth 实例发起网络请求以获取用户记录,这样可以获得用户的最新信息,但需要进行一次网络请求。
  • getSession 当你需要原始会话(访问令牌、刷新令牌和过期时间)时使用。例如,将访问令牌转发到另一个服务。会话是直接从本地存储加载的,并不会重新向认证服务器验证,因此当存储与客户端共享(如 cookies、请求头)时,嵌入的用户对象不应单独信任。要验证身份,请使用 getClaims 验证访问令牌,或调用 getUser 获取一个新的、服务器确认的用户记录。

总结:使用 getClaims 来验证身份(通常用于保护页面和数据),当你需要从认证服务器获取最新的用户记录时用 getUser,而当你直接需要访问或刷新令牌时用 getSession,但不要依赖它返回的用户对象来做授权决策。

1
import { type NextRequest } from 'next/server'
2
import { updateSession } from '@/lib/supabase/proxy'
3
4
export async function proxy(request: NextRequest) {
5
return await updateSession(request)
6
}
7
8
export const config = {
9
matcher: [
10
/*
11
* Match all request paths except for the ones starting with:
12
* - _next/static (static files)
13
* - _next/image (image optimization files)
14
* - favicon.ico (favicon file)
15
* Feel free to modify this pattern to include more paths.
16
*/
17
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
18
],
19
}
View source

恭喜 #

🌐 Congratulations

你完成了!回顾一下,你已经成功地:

🌐 You're done! To recap, you've successfully:

  • 从服务器操作中调用了 Supabase。
  • 从服务器组件调用了 Supabase。
  • 设置一个 Supabase 客户端工具,以便从客户端组件调用 Supabase。如果你需要从客户端组件调用 Supabase,比如设置实时订阅,就可以使用它。
  • 设置代理以自动刷新 Supabase Auth 会话。

你现在可以在客户端或服务器端代码中使用任何 Supabase 功能了!

🌐 You can now use any Supabase features from your client or server code!

缓存注意事项 #

🌐 Caching considerations

如果你的应用使用 ISR(增量静态再生成)或者部署在 CDN 后面,HTTP 响应的缓存可能会导致用户收到别人的会话。当会话被刷新时,新令牌会通过 Set-Cookie 写入响应。如果该响应被缓存并提供给其他用户,那么这个用户就会以错误的身份登录。

🌐 If your app uses ISR (Incremental Static Regeneration) or is deployed behind a CDN, caching of HTTP responses can cause users to receive another user's session. When a session is refreshed, the new token is written to the response via Set-Cookie. If that response is cached and served to a different user, that user will be signed in as the wrong person.

详细信息和特定框架的示例,请参阅 高级 Auth 服务器端渲染指南

🌐 See the advanced Auth server-side rendering guide for details and framework-specific examples.

下一步 #

🌐 Next steps