身份验证
2026年9月6日
登录别从零造。本篇按 Better Auth 记一条能跑通的集成:邮箱密码 + GitHub,数据放 PostgreSQL + Prisma。Auth.js、Clerk 是同类选项,选型看数据库和要不要托管。
为什么用它
- 邮箱、OAuth、Session / Cookie 都有现成插件
- 适配 Prisma、Drizzle,库可以是 Postgres / MySQL / SQLite / Mongo
- Next、Hono 都有 handler
密钥、回调 URL 只放环境变量。
安装和 env
pnpm add better-auth prisma @prisma/client
pnpm add -D prisma
npx prisma init
bash
BETTER_AUTH_SECRET="用 openssl rand -base64 32 生成"
BETTER_AUTH_URL=http://localhost:3000
DATABASE_URL="postgresql://postgres:123456@localhost:5432/auth"
bash
auth 实例
src/lib/auth.ts:
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import prisma from "@/lib/prisma";
export const auth = betterAuth({
database: prismaAdapter(prisma, { provider: "postgresql" }),
emailAndPassword: { enabled: true },
});
ts
生成表结构:
npx auth@latest generate
npx prisma migrate dev --name auth
npx prisma generate
bash
会得到 User、Session、Account、Verification 一类模型。字段以生成结果为准,不要手抄过期 schema。
挂 Route Handler
app/api/auth/[...all]/route.ts:
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";
export const { GET, POST } = toNextJsHandler(auth);
ts
客户端
import { createAuthClient } from "better-auth/react";
export const authClient = createAuthClient({
baseURL: process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000",
});
export const { signIn, signUp, useSession } = authClient;
ts
baseURL 要和 BETTER_AUTH_URL 一致。
"use client";
import { signIn, signUp } from "@/lib/auth-client";
import { useState } from "react";
export default function AuthForm() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [name, setName] = useState("");
return (
<>
<button
type="button"
onClick={() => signUp.email({ email, password, name })}
>
注册
</button>
<button
type="button"
onClick={() => signIn.email({ email, password })}
>
登录
</button>
</>
);
}
tsx
返回 { data, error },按 error 提示即可。
GitHub
- GitHub → Settings → Developer settings → OAuth App
- Callback:
http://localhost:3000/api/auth/callback/github(生产换域名) - env:
GITHUB_CLIENT_ID、GITHUB_CLIENT_SECRET
socialProviders: {
github: {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
},
},
ts
await signIn.social({ provider: "github" });
ts
成功会跳到 GitHub 授权,回来带会话。保护页面用 useSession 或在服务端查 session,未登录 redirect('/login')。和前面 Proxy 里查 cookie 是同一类事。
下一篇:接口层用 Hono 挂进 Next。