钩子函数
Better Auth 中的 Hooks(钩子)允许您"钩入"生命周期并执行自定义逻辑。它们提供了一种无需编写完整插件即可自定义 Better Auth 行为的方式。
如果您需要对某个端点进行自定义调整,我们强烈建议使用钩子,而不是在 Better Auth 之外创建另一个端点。
Before Hooks(前置钩子)
前置钩子在端点执行之前运行。使用它们来修改请求、预先验证数据或提前返回。
示例:强制邮箱域名限制
此钩子确保用户只有在邮箱以 @example.com
结尾时才能注册:
import { betterAuth } from "better-auth";
import { createAuthMiddleware, APIError } from "better-auth/api";
export const auth = betterAuth({
hooks: {
before: createAuthMiddleware(async (ctx) => {
if (ctx.path !== "/sign-up/email") {
return;
}
if (!ctx.body?.email.endsWith("@example.com")) {
throw new APIError("BAD_REQUEST", {
message: "Email must end with @example.com",
});
}
}),
},
});
示例:修改请求上下文
要在继续之前调整请求上下文:
import { betterAuth } from "better-auth";
import { createAuthMiddleware } from "better-auth/api";
export const auth = betterAuth({
hooks: {
before: createAuthMiddleware(async (ctx) => {
if (ctx.path === "/sign-up/email") {
return {
context: {
...ctx,
body: {
...ctx.body,
name: "John Doe",
},
}
};
}
}),
},
});
After Hooks(后置钩子)
后置钩子在端点执行之后运行。使用它们来修改响应。
示例:当新用户注册时向您的频道发送通知
import { betterAuth } from "better-auth";
import { createAuthMiddleware } from "better-auth/api";
import { sendMessage } from "@/lib/notification"
export const auth = betterAuth({
hooks: {
after: createAuthMiddleware(async (ctx) => {
if(ctx.path.startsWith("/sign-up")){
const newSession = ctx.context.newSession;
if(newSession){
sendMessage({
type: "user-register",
name: newSession.user.name,
})
}
}
}),
},
});
上下文对象 (Ctx)
当您调用 createAuthMiddleware
时,会传入一个 ctx
对象,该对象提供了许多有用的属性。包括:
- 路径:
ctx.path
获取当前端点路径。 - 请求体:
ctx.body
获取解析后的请求体(适用于 POST 请求)。 - 请求头:
ctx.headers
访问请求头。 - 请求对象:
ctx.request
访问请求对象(在仅服务器端点中可能不存在)。 - 查询参数:
ctx.query
访问查询参数。 - 上下文:
ctx.context
与认证相关的上下文,可用于访问新会话、认证 cookie 配置、密码哈希、配置等。
以及更多。
请求响应
这些实用工具允许您从钩子中获取请求信息并发送响应。
JSON 响应
使用 ctx.json
发送 JSON 响应:
const hook = createAuthMiddleware(async (ctx) => {
return ctx.json({
message: "Hello World",
});
});
重定向
使用 ctx.redirect
重定向用户:
import { createAuthMiddleware } from "better-auth/api";
const hook = createAuthMiddleware(async (ctx) => {
throw ctx.redirect("/sign-up/name");
});
Cookies(Cookie 操作)
- 设置 Cookie:使用
ctx.setCookies
或ctx.setSignedCookie
。 - 获取 Cookie:使用
ctx.getCookies
或ctx.getSignedCookies
。
示例:
import { createAuthMiddleware } from "better-auth/api";
const hook = createAuthMiddleware(async (ctx) => {
ctx.setCookies("my-cookie", "value");
await ctx.setSignedCookie("my-signed-cookie", "value", ctx.context.secret, {
maxAge: 1000,
});
const cookie = ctx.getCookies("my-cookie");
const signedCookie = await ctx.getSignedCookies("my-signed-cookie");
});
错误处理
使用 APIError
抛出具有特定状态码和消息的错误:
import { createAuthMiddleware, APIError } from "better-auth/api";
const hook = createAuthMiddleware(async (ctx) => {
throw new APIError("BAD_REQUEST", {
message: "无效请求",
});
});
Context(上下文)
ctx
对象内部包含另一个 context
对象,用于存储与身份验证相关的上下文信息。包括在 after hook 中新建的会话、Cookie 配置、密码哈希器等。
新建会话
端点运行后新建的会话。仅存在于 after hook 中。
createAuthMiddleware(async (ctx) => {
const newSession = ctx.context.newSession
});
返回值
从 hook 返回的值会传递给链中的下一个 hook。
createAuthMiddleware(async (ctx) => {
const returned = ctx.context.returned; // 这可能是成功响应或 APIError
});
响应头
由在此 hook 之前运行的端点和 hook 添加的响应头。
createAuthMiddleware(async (ctx) => {
const responseHeaders = ctx.context.responseHeaders;
});
预定义的身份验证 Cookie
访问 BetterAuth 预定义的 Cookie 属性:
createAuthMiddleware(async (ctx) => {
const cookieName = ctx.context.authCookies.sessionToken.name;
});
密钥 (Secret)
您可以通过 ctx.context.secret
访问您的 auth 实例的 secret
。
密码 (Password)
密码对象提供 hash
和 verify
方法:
ctx.context.password.hash
:允许您对给定密码进行哈希处理。ctx.context.password.verify
:允许您验证给定的password
和hash
是否匹配。
适配器 (Adapter)
适配器暴露了 Better Auth 使用的适配器方法,包括 findOne
、findMany
、create
、delete
、update
和 updateMany
。通常,您应该使用 ORM 中的实际 db
实例,而不是这个适配器。
内部适配器 (Internal Adapter)
这些是对数据库执行特定操作的调用,例如 createUser
、createSession
、updateSession
等。
使用内部适配器而不是直接使用数据库可能更有用,因为它提供了对 databaseHooks
的支持、适当的 secondaryStorage
支持等功能。如果您需要执行与此内部适配器操作类似的查询,值得考虑使用它。
生成 ID (generateId)
您可以使用 ctx.context.generateId
来生成 ID,适用于各种场景。
可复用的钩子 (Reusable Hooks)
如果需要在多个端点中复用某个钩子,可以考虑创建一个插件。更多信息请参阅插件文档。