Skip to content
Auth

为 SSR 创建 Supabase 客户端

Configure your Supabase client to use cookies

学习如何配置你的 Supabase 客户端来使用 cookies。这样你的应用就可以在用户已登录的情况下在服务器上渲染了。

🌐 Learn how to configure your Supabase client to use cookies. Your app can then render on the server with the user already signed in.

使用 Supabase 进行服务器端渲染(SSR)需要基于 cookie 的会话存储。@supabase/ssr 包可以为 JavaScript 和 TypeScript 应用处理这个问题。

🌐 Server-Side Rendering (SSR) with Supabase requires cookie-based session storage. The @supabase/ssr package handles this for JavaScript and TypeScript applications.

使用此指南来:

🌐 Use this guide to:

  1. 安装这些包。
  2. 设置环境变量。
  3. 为你的框架创建一个客户端。

参考这些参考部分来更好地决定如何验证用户和缓存响应:

🌐 Refer to these reference sections to make better decisions about verifying users and caching responses:

安装 #

🌐 Install

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

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

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.

NEXT_PUBLIC_SUPABASE_URL=supabase_project_url
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.

在你写检查用户身份的代码之前,先看看选择认证方法。

🌐 Before you write code that checks who the user is, see Choosing an auth method.

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

🌐 Write utility functions to create Supabase clients [#nextjs-utility-functions]

要从 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. 将刷新后的 Auth 令牌传递给服务器组件,这样它们就不会自己尝试刷新同一个令牌。这就是保持用户持续登录的方式。这是通过 request.cookies.set 实现的。
  3. 将更新后的认证令牌传递给浏览器,以替换旧的令牌。这是用 response.cookies.set 完成的。

在你的项目根目录下创建一个 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.

import { createBrowserClient } from '@supabase/ssr'
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!
)
}
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.

返回 setAll 最后创建的 supabaseResponse 对象。之前的响应不会带上更新的 cookie,所以用户在下一次请求时会被登出。

🌐 Return the supabaseResponse object that setAll last built. An earlier response doesn't carry the refreshed cookies, so the user is signed out on the next request.

当你需要返回不同的响应时,先把 cookies 和缓存头复制过去:

🌐 When you need to return a different response, copy the cookies and the cache headers onto it first:

const myNewResponse = NextResponse.next({ request })
myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())
for (const header of ['cache-control', 'expires', 'pragma']) {
const value = supabaseResponse.headers.get(header)
if (value) myNewResponse.headers.set(header, value)
}
return myNewResponse
import { type NextRequest } from 'next/server'
import { updateSession } from '@/lib/supabase/proxy'
export async function proxy(request: NextRequest) {
return await updateSession(request)
}
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* Feel free to modify this pattern to include more paths.
*/
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
],
}
View source

恭喜 #

🌐 Congratulations [#nextjs-congratulations]

总结一下,你已经:

🌐 To recap, you've:

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

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

🌐 You can now use any Supabase feature from your client or server code.

选择认证方式 #

🌐 Choosing an auth method

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 解码,而不是用户查找。当访问令牌快到期时,getClaims 会在验证前刷新会话,这就是服务器渲染会话保持活跃的方式。
  • [getUser](/docs/reference/javascript/auth-getuser) 会向项目的 Auth 实例发起网络请求以获取用户记录,这样可以获得用户的最新信息,但需要进行一次网络请求。
  • getSession 当你需要原始会话(访问令牌、刷新令牌和过期时间)时使用。例如,将访问令牌转发到另一个服务。会话是直接从本地存储加载的,并不会重新向认证服务器验证,因此当存储与客户端共享(如 cookies、请求头)时,嵌入的用户对象不应单独信任。要验证身份,请使用 getClaims 验证访问令牌,或调用 getUser 获取一个新的、服务器确认的用户记录。

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

缓存注意事项 #

🌐 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