数据库
适配器
Better Auth 需要数据库连接来存储数据。它内置了一个名为 Kysely 的查询构建器来管理和查询数据库。数据库将用于存储用户、会话等数据。插件也可以定义自己的数据库表来存储数据。
你可以通过在数据库选项中传入支持的数据库实例、方言实例或 Kysely 实例来为 Better Auth 提供数据库连接。
你可以在其他关系型数据库文档中了解更多关于支持的 Kysely 方言。如果你使用的是 ORM,你可以在文档侧边栏的同一类别中找到我们支持的 ORM 适配器。
命令行工具
Better Auth 提供了一个命令行工具来管理数据库迁移和生成架构。
运行迁移
命令行工具会检查你的数据库并提示你添加缺失的表或使用新列更新现有表。这仅支持内置的 Kysely 适配器。对于其他适配器,你可以使用 generate
命令来创建架构,并通过你的 ORM 处理迁移。
生成数据库表
Better Auth 还提供了 generate
命令来生成数据库表。generate
命令会创建 Better Auth 所需的架构。如果你使用的是 Prisma 或 Drizzle 等数据库适配器,此命令将为你的 ORM 生成相应的架构。如果你使用内置的 Kysely 适配器,它将生成一个可以直接在数据库中运行的 SQL 文件。
有关命令行工具的更多信息,请参阅命令行工具文档。
如果你更喜欢手动添加表,也可以这样做。下面描述了 Better Auth 所需的核心架构,你可以在插件文档中找到插件所需的其他架构。
二级存储
Better Auth 中的二级存储允许你使用键值存储来管理会话数据、速率限制计数器等。当你想要将这些密集记录的存储卸载到高性能存储甚至 RAM 时,这会很有用。
实现
要使用二级存储,请实现 SecondaryStorage
接口:
然后,将你的实现提供给 betterAuth
函数:
示例:Redis 实现
这是一个使用 Redis 的基本示例:
这个实现允许 Better Auth 使用 Redis 来存储会话数据和速率限制计数器。你还可以为键名添加前缀。
核心架构
Better Auth 需要在数据库中存在以下表。类型使用 typescript
格式。你可以在数据库中使用相应的类型。
用户表
表名:user
Field Name | Type | Key | Description |
---|---|---|---|
id | string | 用户的唯一标识符 | |
name | string | - | 用户选择的显示名称 |
string | - | 用户的电子邮件地址,用于通信和登录 | |
emailVerified | boolean | - | 用户的电子邮件是否已验证 |
image | string | 用户的头像 URL | |
createdAt | Date | - | 用户账户创建的时间戳 |
updatedAt | Date | - | 用户信息最后更新的时间戳 |
会话表
表名:session
Field Name | Type | Key | Description |
---|---|---|---|
id | string | 会话的唯一标识符 | |
userId | string | 用户的 ID | |
token | string | - | 唯一的会话令牌 |
expiresAt | Date | - | 会话过期的时间 |
ipAddress | string | 设备的 IP 地址 | |
userAgent | string | 设备的用户代理信息 | |
createdAt | Date | - | 会话创建的时间戳 |
updatedAt | Date | - | 会话更新的时间戳 |
账户表
表名:account
Field Name | Type | Key | Description |
---|---|---|---|
id | string | 账户的唯一标识符 | |
userId | string | 用户的 ID | |
accountId | string | - | SSO 提供的账户 ID,或对于凭证账户等于 userId |
providerId | string | - | 提供者的 ID |
accessToken | string | 账户的访问令牌,由提供者返回 | |
refreshToken | string | 账户的刷新令牌,由提供者返回 | |
accessTokenExpiresAt | Date | 访问令牌过期的时间 | |
refreshTokenExpiresAt | Date | 刷新令牌过期的时间 | |
scope | string | 账户的作用域,由提供者返回 | |
idToken | string | 提供者返回的 ID 令牌 | |
password | string | 账户的密码,主要用于邮箱和密码认证 | |
createdAt | Date | - | 账户创建的时间戳 |
updatedAt | Date | - | 账户更新的时间戳 |
验证表
表名:verification
Field Name | Type | Key | Description |
---|---|---|---|
id | string | 验证的唯一标识符 | |
identifier | string | - | 验证请求的标识符 |
value | string | - | 要验证的值 |
expiresAt | Date | - | 验证请求过期的时间 |
createdAt | Date | - | 验证请求创建的时间戳 |
updatedAt | Date | - | 验证请求更新的时间戳 |
自定义表
Better Auth 允许你自定义核心架构的表名和列名。你还可以通过向用户和会话表添加额外字段来扩展核心架构。
自定义表名
你可以通过在认证配置中使用 modelName
和 fields
属性来自定义核心架构的表名和列名:
在你的代码中的类型推断仍将使用原始字段名(例如,使用 user.name
,而不是 user.full_name
)。
要为插件自定义表名和列名,你可以在插件配置中使用 schema
属性:
扩展核心架构
Better Auth 提供了一种类型安全的方式来扩展 user
和 session
架构。你可以在认证配置中添加自定义字段,命令行工具将自动更新数据库架构。这些额外字段将在 useSession
、signUp.email
和其他处理用户或会话对象的端点中正确推断。
要添加自定义字段,请在认证配置的 user
或 session
对象中使用 additionalFields
属性。additionalFields
对象使用字段名作为键,每个值都是一个包含以下内容的 FieldAttributes
对象:
type
:字段的数据类型(例如:"string"、"number"、"boolean")。required
:表示字段是否必填的布尔值。defaultValue
:字段的默认值(注意:这只适用于 JavaScript 层;在数据库中,该字段将是可选的)。input
:这决定了在创建新记录时是否可以提供值(默认:true
)。如果有一些额外字段,比如role
,在注册时不应该由用户提供,你可以将其设置为false
。
以下是如何使用额外字段扩展用户架构的示例:
现在你可以在应用程序逻辑中访问这些额外字段。
查看TypeScript文档以了解更多关于如何在客户端推断额外字段的信息。
如果你使用社交/OAuth 提供者,你可能想要提供 mapProfileToUser
来将配置文件数据映射到用户对象。这样,你就可以从提供者的配置文件中填充额外字段。
示例:将配置文件映射到用户的 firstName
和 lastName
ID 生成
Better Auth 默认会为用户、会话和其他实体生成唯一 ID。如果你想自定义 ID 的生成方式,可以在认证配置的 advanced.database.generateId
选项中进行配置。
你也可以通过将 advanced.database.generateId
选项设置为 false
来禁用 ID 生成。这将假设你的数据库会自动生成 ID。
示例:自动数据库 ID
数据库钩子
数据库钩子允许你定义在 Better Auth 核心数据库操作生命周期中执行的自定义逻辑。你可以为以下模型创建钩子:user、session 和 account。
你可以定义两种类型的钩子:
1. 前置钩子
- 目的:此钩子在相应实体(用户、会话或账户)创建或更新之前调用。
- 行为:如果钩子返回
false
,操作将被中止。如果返回数据对象,它将替换原始负载。
2. 后置钩子
- 目的:此钩子在相应实体创建或更新之后调用。
- 行为:你可以在实体成功创建或更新后执行额外的操作或修改。
使用示例
抛出错误
如果你想阻止数据库钩子继续执行,你可以使用从 better-auth/api
导入的 APIError
类抛出错误。
与标准钩子一样,数据库钩子也提供了一个 ctx
对象,它提供了各种有用的属性。在钩子文档中了解更多信息。
插件架构
插件可以在数据库中定义自己的表来存储额外数据。它们还可以向核心表添加列来存储额外数据。例如,双因素认证插件向 user
表添加了以下列:
twoFactorEnabled
:用户是否启用了双因素认证。twoFactorSecret
:用于生成 TOTP 码的密钥。twoFactorBackupCodes
:用于账户恢复的加密备份码。
要向数据库添加新表和列,你有两个选项:
命令行工具
:使用 migrate 或 generate 命令。这些命令将扫描你的数据库并指导你添加任何缺失的表或列。
手动方法
:按照插件文档中的说明手动添加表和列。
这两种方法都确保你的数据库架构与插件的要求保持同步。