首页
/ Better Auth 插件开发指南:从零开始构建生日验证插件

Better Auth 插件开发指南:从零开始构建生日验证插件

2025-07-06 01:15:26作者:彭桢灵Jeremy

前言

在现代Web应用开发中,认证系统是保障应用安全的核心组件。Better Auth作为一个现代化的认证解决方案,提供了强大的插件机制,允许开发者扩展其核心功能。本文将带领你从零开始开发一个生日验证插件,通过这个实践过程,你将掌握Better Auth插件开发的核心概念和技巧。

准备工作

在开始之前,请确保你已经完成了Better Auth的基础配置。这个插件开发指南假设你已经:

  1. 完成了Better Auth的初始安装
  2. 配置好了基本的认证环境
  3. 熟悉TypeScript的基本语法

插件规划

我们计划开发一个生日验证插件,主要功能包括:

  1. 记录用户的生日信息
  2. 验证用户年龄是否超过5岁
  3. 提供前后端一致的验证逻辑

服务器插件开发

Better Auth的插件系统采用前后端分离的设计模式,我们先从服务器端插件开始。

基础结构创建

首先创建一个名为birthday-plugin的文件夹,并在其中创建index.ts文件:

birthday-plugin/
└── index.ts

index.ts中,我们定义插件的基本结构:

import { createAuthClient } from "better-auth/client";
import type { BetterAuthPlugin } from "better-auth";

export const birthdayPlugin = () =>
  ({
    id: "birthdayPlugin",
  } satisfies BetterAuthPlugin);

虽然这只是一个空壳,但已经是一个合法的Better Auth插件了。

数据模型定义

为了存储用户的生日信息,我们需要扩展用户模型:

export const birthdayPlugin = () =>
  ({
    id: "birthdayPlugin",
    schema: {
      user: {
        fields: {
          birthday: {
            type: "date", // 支持string, number, boolean, date类型
            required: true, // 该字段是否为必填项
            unique: false, // 该字段是否需要唯一
            references: null // 关联其他表的引用
          },
        },
      },
    },
  } satisfies BetterAuthPlugin);

这个模式定义会被Better Auth的CLI工具用来生成数据库迁移脚本。

认证逻辑实现

我们需要在用户注册时验证其年龄是否超过5岁。这里使用Better Auth的钩子(Hooks)系统:

import { APIError } from "better-auth/api";
import { createAuthMiddleware } from "better-auth/plugins";

export const birthdayPlugin = () => ({
    // ...之前的配置
    hooks: {
      before: [
        {
          matcher: (context) => context.path.startsWith("/sign-up/email"),
          handler: createAuthMiddleware(async (ctx) => {
            const { birthday } = ctx.body;
            if(!(birthday instanceof Date)) {
              throw new APIError("BAD_REQUEST", { 
                message: "生日必须是Date类型" 
              });
            }

            const today = new Date();
            const fiveYearsAgo = new Date(
              today.setFullYear(today.getFullYear() - 5)
            );

            if(birthday >= fiveYearsAgo) {
              throw new APIError("BAD_REQUEST", { 
                message: "用户年龄必须超过5岁" 
              });
            }

            return { context: ctx };
          }),
        },
      ],
    },
} satisfies BetterAuthPlugin)

这段代码实现了:

  1. 验证生日字段是否为Date类型
  2. 计算5年前的日期
  3. 比较用户生日是否早于5年前
  4. 根据结果允许或拒绝注册请求

客户端插件开发

虽然我们的生日插件主要逻辑在服务端,但为了保持一致性,我们仍然需要创建客户端插件。

创建client.ts文件:

birthday-plugin/
├── index.ts
└── client.ts

客户端插件代码:

import { BetterAuthClientPlugin } from "better-auth";
import type { birthdayPlugin } from "./index";

type BirthdayPlugin = typeof birthdayPlugin;

export const birthdayClientPlugin = () => {
  return {
    id: "birthdayPlugin",
    $InferServerPlugin: {} as ReturnType<BirthdayPlugin>,
  } satisfies BetterAuthClientPlugin;
};

这个客户端插件主要作用是继承服务端插件定义的类型,确保前后端类型一致。

插件集成

服务端集成

在服务端配置文件中引入插件:

import { betterAuth } from "better-auth";
import { birthdayPlugin } from "./birthday-plugin";
 
export const auth = betterAuth({
    plugins: [
      birthdayPlugin(),
    ]
});

客户端集成

在客户端配置文件中引入插件:

import { createAuthClient } from "better-auth/client";
import { birthdayClientPlugin } from "./birthday-plugin/client";
 
const authClient = createAuthClient({
    plugins: [
      birthdayClientPlugin()
    ]
});

数据库迁移

最后,执行以下命令生成数据库迁移脚本:

npx @better-auth/cli@latest generate

总结

通过本教程,我们完成了一个完整的Better Auth插件开发流程,包括:

  1. 插件规划与设计
  2. 服务端插件开发
  3. 数据模型定义
  4. 认证逻辑实现
  5. 客户端插件开发
  6. 前后端集成

这个生日验证插件虽然简单,但涵盖了Better Auth插件开发的核心概念。你可以基于这个模式开发更复杂的认证逻辑,如:

  • 多因素认证
  • 社交账号绑定
  • 用户行为分析等

Better Auth的插件系统为认证功能的扩展提供了无限可能,希望本教程能为你开发更强大的认证功能打下坚实基础。