阅读时间 2 分钟最后更新: 2025-12-31 12:12

认证

本模板使用 Better Auth 进行认证,提供安全灵活的认证系统。

功能特性

  • 邮箱/密码 - 传统的邮箱和密码认证
  • 社交登录 - OAuth 提供商(Google、GitHub 等)
  • 魔法链接 - 无密码邮箱认证
  • 双因素认证 - 通过 2FA 增强安全性
  • 会话管理 - 安全的会话处理

配置

环境变量

.env.local 中添加以下内容:

# Better Auth 配置
BETTER_AUTH_SECRET="your-secret-key-min-32-chars"
BETTER_AUTH_URL="http://localhost:3000"

# OAuth 提供商(可选)
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"

GITHUB_CLIENT_ID="your-github-client-id"
GITHUB_CLIENT_SECRET="your-github-client-secret"

认证配置

认证配置位于 src/lib/auth.ts

import { betterAuth } from 'better-auth'
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
import { db } from './database'

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: 'pg', // 或 'sqlite'
  }),
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
  },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    },
    github: {
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!,
    },
  },
})

使用方法

客户端认证

在 React 组件中使用认证客户端:

'use client'

import { useSession, signIn, signOut } from '@/lib/auth-client'

export function AuthButton() {
  const { data: session, isPending } = useSession()

  if (isPending) {
    return <div>加载中...</div>
  }

  if (session) {
    return (
      <div>
        <p>欢迎,{session.user.name}!</p>
        <button onClick={() => signOut()}>退出登录</button>
      </div>
    )
  }

  return (
    <button onClick={() => signIn.email({ email, password })}>
      登录
    </button>
  )
}

服务端认证

在服务端组件中检查认证:

import { auth } from '@/lib/auth'
import { headers } from 'next/headers'

export default async function ProtectedPage() {
  const session = await auth.api.getSession({
    headers: await headers(),
  })

  if (!session) {
    redirect('/login')
  }

  return <div>{session.user.name} 的受保护内容</div>
}

API 路由保护

保护您的 API 路由:

import { auth } from '@/lib/auth'
import { headers } from 'next/headers'
import { NextResponse } from 'next/server'

export async function GET() {
  const session = await auth.api.getSession({
    headers: await headers(),
  })

  if (!session) {
    return NextResponse.json({ error: '未授权' }, { status: 401 })
  }

  return NextResponse.json({ data: '受保护的数据' })
}

自定义

自定义登录页面

src/app/[lang]/(auth)/login/page.tsx 创建自定义登录页面:

import { LoginForm } from '@/components/auth/LoginForm'

export default function LoginPage() {
  return (
    <div className="min-h-screen flex items-center justify-center">
      <LoginForm />
    </div>
  )
}

邮件模板

src/lib/email/templates/ 中自定义邮件模板:

  • verification.tsx - 邮箱验证
  • password-reset.tsx - 密码重置
  • magic-link.tsx - 魔法链接登录

安全最佳实践

  1. 在生产环境中使用 HTTPS
  2. 设置带有 httpOnlysecure 标志的安全 Cookie
  3. 在认证端点上实现速率限制
  4. 为敏感账户启用 2FA
  5. 对长期会话进行定期会话轮换

故障排除

常见问题

会话不持久:

  • 检查 BETTER_AUTH_URL 是否与您的域名匹配
  • 验证生产环境中的 Cookie 设置

OAuth 重定向错误:

  • 确保在提供商设置中配置了回调 URL
  • 检查环境变量是否正确设置

邮件未发送:

  • 验证 Resend API 密钥是否已配置
  • 检查邮件模板是否有错误