钩子
Better Auth 中的钩子允许你“挂入”生命周期并执行自定义逻辑。它们提供了一种在不编写完整插件的情况下自定义 Better Auth 行为的方法。
【Hooks in Better Auth let you "hook into" the lifecycle and execute custom logic. They provide a way to customize Better Auth's behavior without writing a full plugin. 】
我们强烈建议在需要对端点进行自定义调整时使用 hooks,而不是在 Better Auth 之外创建另一个端点。
钩子之前
【Before Hooks】
前置钩子 会在端点执行 之前 运行。可以用它们来修改请求、预先验证数据,或提前返回。
示例:强制执行电子邮件域限制
【Example: Enforce Email Domain Restriction】
此钩子确保用户只有在其电子邮件以 @example.com 结尾时才能注册:
【This hook ensures that users can only sign up if their email ends with @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",
});
}
}),
},
});示例:修改请求上下文
【Example: Modify Request Context】
在继续之前调整请求上下文:
【To adjust the request context before proceeding:】
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】
后置钩子 在端点执行 之后 运行。可用它们来修改响应。
示例:当有新用户注册时向你的通道发送通知
【Example: Send a notification to your channel when a new user is registered】
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 对象,该对象提供了许多有用的属性,包括:
【When you call createAuthMiddleware a ctx object is passed that provides a lot of useful properties. Including:】
- 路径: 使用
ctx.path获取当前端点路径。 - 正文:
ctx.body用于解析后的请求正文(适用于 POST 请求)。 - 头部信息: 使用
ctx.headers访问请求头。 - 请求: 使用
ctx.request访问请求对象(在仅服务器端的端点可能不存在)。 - 查询参数: 使用
ctx.query访问查询参数。 - 上下文:
ctx.context与认证相关的上下文,可用于访问新会话、认证 Cookie 配置、密码哈希、配置等...
等等。
【and more.】
请求响应
【Request Response】
这个工具允许你从钩子获取请求信息并发送响应。
【This utilities allows you to get request information and to send response from a hook. 】
JSON 响应
【JSON Responses】
使用 ctx.json 发送 JSON 响应:
【Use ctx.json to send JSON responses:】
const hook = createAuthMiddleware(async (ctx) => {
return ctx.json({
message: "Hello World",
});
});重定向
【Redirects】
使用 ctx.redirect 重定向用户:
【Use ctx.redirect to redirect users:】
import { createAuthMiddleware } from "better-auth/api";
const hook = createAuthMiddleware(async (ctx) => {
throw ctx.redirect("/sign-up/name");
});Cookies
- 设置 Cookie:
ctx.setCookies或ctx.setSignedCookie。 - 获取 cookies:
ctx.getCookies或ctx.getSignedCookie。
示例:
【Example:】
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.getSignedCookie("my-signed-cookie");
});错误
【Errors】
针对特定的状态码和消息使用 APIError 抛出错误:
【Throw errors with APIError for a specific status code and message:】
import { createAuthMiddleware, APIError } from "better-auth/api";
const hook = createAuthMiddleware(async (ctx) => {
throw new APIError("BAD_REQUEST", {
message: "Invalid request",
});
});上下文
【Context】
ctx 对象内部包含另一个 context 对象,用于保存与身份验证相关的上下文信息。包括在 after 钩子中新创建的会话、cookie 配置、密码哈希等内容。
【The ctx object contains another context object inside that's meant to hold contexts related to auth. Including a newly created session on after hook, cookies configuration, password hasher and so on. 】
新会话
【New Session】
在运行端点后创建的新会话。这只存在于后置钩子中。
【The newly created session after an endpoint is run. This only exist in after hook.】
createAuthMiddleware(async (ctx) => {
const newSession = ctx.context.newSession
});已返回
【Returned】
钩子返回的值会传递给链中的下一个钩子。
【The returned value from the hook is passed to the next hook in the chain.】
createAuthMiddleware(async (ctx) => {
const returned = ctx.context.returned; //this could be a successful response or an APIError
});响应头
【Response Headers】
在此钩子之前运行的端点和钩子添加的响应头。
【The response headers added by endpoints and hooks that run before this hook.】
createAuthMiddleware(async (ctx) => {
const responseHeaders = ctx.context.responseHeaders;
});预定义认证 Cookie
【Predefined Auth Cookies】
访问 BetterAuth 的预定义 Cookie 属性:
【Access BetterAuth’s predefined cookie properties:】
createAuthMiddleware(async (ctx) => {
const cookieName = ctx.context.authCookies.sessionToken.name;
});秘密
【Secret】
你可以在 ctx.context.secret 上访问你的认证实例的 secret
【You can access the secret for your auth instance on ctx.context.secret】
密码
【Password】
密码对象提供者 hash 和 verify
【The password object provider hash and verify】
ctx.context.password.hash:允许你对给定的密码进行哈希处理。ctx.context.password.verify:让你可以验证提供的password和hash。
适配器
【Adapter】
Adapter 提供了 Better Auth 使用的适配器方法,包括 findOne、findMany、create、delete、update 和 updateMany。通常,你应该使用 ORM 中实际的 db 实例,而不是这个适配器。
【Adapter exposes the adapter methods used by Better Auth. Including findOne, findMany, create, delete, update and updateMany. You generally should use your actually db instance from your orm rather than this adapter.】
内部适配器
【Internal Adapter】
这些是对你的数据库执行特定操作的调用。createUser、createSession、updateSession…
【These are calls to your db that perform specific actions. createUser, createSession, updateSession...】
这可能比直接使用你的数据库更有用,可以访问 databaseHooks、提供适当的 secondaryStorage 支持等等。如果你要进行类似于内部适配器操作中存在的查询,值得看看。
【This may be useful to use instead of using your db directly to get access to databaseHooks, proper secondaryStorage support and so on. If you're make a query similar to what exist in this internal adapter actions it's worth a look.】
生成 ID
【generateId】
你可以使用 ctx.context.generateId 来生成各种用途的 Id。
【You can use ctx.context.generateId to generate Id for various reasons.】
可复用钩子
【Reusable Hooks】
如果你需要在多个端点之间重用钩子,考虑创建一个插件。更多信息请参阅插件文档。
【If you need to reuse a hook across multiple endpoints, consider creating a plugin. Learn more in the Plugins Documentation.】