Next.js 集成
Better Auth 可以轻松与 Next.js 集成。在开始之前,请确保您已配置 Better Auth 实例。如果您还没有这样做,请查看 安装。
创建 API 路由
我们需要将处理程序挂载到 API 路由。在 /api/auth/[...all] 目录中创建一个路由文件。然后添加以下代码:
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";
export const { GET, POST } = toNextJsHandler(auth.handler);您可以在 better-auth 配置中更改路径,但建议保持为 /api/auth/[...all]
对于 pages 路由,您需要使用 toNodeHandler 而非 toNextJsHandler,并在 config 对象中将 bodyParser 设置为 false。以下是示例:
import { toNodeHandler } from "better-auth/node"
import { auth } from "@/lib/auth"
// Disallow body parsing, we will parse it manually
export const config = { api: { bodyParser: false } }
export default toNodeHandler(auth.handler)创建客户端
创建客户端实例。您可以为文件命名任意名称。这里我们在 lib/ 目录中创建 client.ts 文件。
import { createAuthClient } from "better-auth/react" // make sure to import from better-auth/react
export const authClient = createAuthClient({
//you can pass client configuration here
})创建客户端后,您可以使用它进行注册、登录以及执行其他操作。 其中一些操作是响应式的。客户端使用 nano-store 来存储状态,并在状态更改时重新渲染组件。
客户端还使用 better-fetch 来发出请求。您可以将 fetch 配置传递给客户端。
RSC 和服务器操作
从 auth 实例导出的 api 对象包含您可以在服务器上执行的所有操作。Better Auth 中的每个端点都可以作为函数调用,包括插件端点。
示例:在服务器操作中获取会话
import { auth } from "@/lib/auth"
import { headers } from "next/headers"
const someAuthenticatedAction = async () => {
"use server";
const session = await auth.api.getSession({
headers: await headers()
})
};示例:在 RSC 中获取会话
import { auth } from "@/lib/auth"
import { headers } from "next/headers"
export async function ServerComponent() {
const session = await auth.api.getSession({
headers: await headers()
})
if(!session) {
return <div>Not authenticated</div>
}
return (
<div>
<h1>Welcome {session.user.name}</h1>
</div>
)
}服务器操作 Cookie
当您在服务器操作中调用需要设置 Cookie 的函数(如 signInEmail 或 signUpEmail)时,Cookie 不会被设置。这是因为服务器操作需要使用 Next.js 的 cookies 帮助程序来设置 Cookie。
为了简化此过程,您可以使用 nextCookies 插件,该插件会在响应中存在 Set-Cookie 标头时自动为您设置 Cookie。
import { betterAuth } from "better-auth";
import { nextCookies } from "better-auth/next-js";
export const auth = betterAuth({
//...your config
plugins: [nextCookies()] // make sure this is the last plugin in the array
})现在,当您调用设置 Cookie 的函数时,它们将被自动设置。
"use server";
import { auth } from "@/lib/auth"
const signIn = async () => {
await auth.api.signInEmail({
body: {
email: "user@email.com",
password: "password",
}
})
}中间件
在 Next.js 中间件中,建议仅检查会话 Cookie 的存在来处理重定向。以避免通过发出 API 或数据库调用来阻塞请求。
您可以使用 Better Auth 中的 getSessionCookie 帮助程序来实现此目的:
getSessionCookie() 函数不会自动引用 auth.ts 中指定的 auth 配置。因此,如果您自定义了 Cookie 名称或前缀,您需要确保 getSessionCookie() 中的配置与 auth.ts 中定义的配置匹配。
import { NextRequest, NextResponse } from "next/server";
import { getSessionCookie } from "better-auth/cookies";
export async function middleware(request: NextRequest) {
const sessionCookie = getSessionCookie(request);
// THIS IS NOT SECURE!
// This is the recommended approach to optimistically redirect users
// We recommend handling auth checks in each page/route
if (!sessionCookie) {
return NextResponse.redirect(new URL("/", request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ["/dashboard"], // Specify the routes the middleware applies to
};安全警告: getSessionCookie 函数仅检查会话 Cookie 的存在;它不会验证它。仅依赖此检查进行安全操作是危险的,因为任何人可以手动创建 Cookie 来绕过它。您必须始终在服务器上验证会话,以保护任何操作或页面。
如果您有自定义 Cookie 名称或前缀,您可以将它传递给 getSessionCookie 函数。
const sessionCookie = getSessionCookie(request, {
cookieName: "my_session_cookie",
cookiePrefix: "my_prefix"
});或者,您可以使用 getCookieCache 帮助程序从 Cookie 缓存中获取会话对象。
import { getCookieCache } from "better-auth/cookies";
export async function middleware(request: NextRequest) {
const session = await getCookieCache(request);
if (!session) {
return NextResponse.redirect(new URL("/sign-in", request.url));
}
return NextResponse.next();
}如何在每个页面/路由中处理身份验证检查
在此示例中,我们在服务器组件中使用 auth.api.getSession 函数获取会话对象,
然后检查会话是否有效。如果无效,我们将用户重定向到登录页面。
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
export default async function DashboardPage() {
const session = await auth.api.getSession({
headers: await headers()
})
if(!session) {
redirect("/sign-in")
}
return (
<div>
<h1>Welcome {session.user.name}</h1>
</div>
)
}对于 Next.js 版本 15.1.7 及以下
如果您需要完整的会话对象,您必须从 /get-session API 路由中获取它。由于 Next.js 中间件不支持直接运行 Node.js API,您必须发出 HTTP 请求。
示例使用 better-fetch,但您可以使用任何 fetch 库。
import { betterFetch } from "@better-fetch/fetch";
import type { auth } from "@/lib/auth";
import { NextRequest, NextResponse } from "next/server";
type Session = typeof auth.$Infer.Session;
export async function middleware(request: NextRequest) {
const { data: session } = await betterFetch<Session>("/api/auth/get-session", {
baseURL: request.nextUrl.origin,
headers: {
cookie: request.headers.get("cookie") || "", // Forward the cookies from the request
},
});
if (!session) {
return NextResponse.redirect(new URL("/sign-in", request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ["/dashboard"], // Apply middleware to specific routes
};对于 Next.js 版本 15.2.0 及以上
从版本 15.2.0 开始,Next.js 允许您在中间件中使用 Node.js 运行时。这意味着您可以直接在中间件中使用 auth.api 对象。
您可以参考 Next.js 文档 以获取有关运行时配置以及如何启用它的更多信息。 在使用新运行时时请小心。它是一个实验性功能,可能会受到破坏性更改的影响。
import { NextRequest, NextResponse } from "next/server";
import { headers } from "next/headers";
import { auth } from "@/lib/auth";
export async function middleware(request: NextRequest) {
const session = await auth.api.getSession({
headers: await headers()
})
if(!session) {
return NextResponse.redirect(new URL("/sign-in", request.url));
}
return NextResponse.next();
}
export const config = {
runtime: "nodejs",
matcher: ["/dashboard"], // Apply middleware to specific routes
};