会话管理
Better Auth 使用传统的基于 Cookie 的会话管理来管理会话。会话存储在 Cookie 中,并在每次请求中发送到服务器。然后服务器验证会话,如果会话有效,则返回用户数据。
会话表
会话表存储会话数据。会话表具有以下字段:
id: 会话令牌。也用作会话 Cookie。userId: 用户的用户 ID。expiresAt: 会话的过期日期。ipAddress: 用户的 IP 地址。userAgent: 用户的用户代理。它存储来自请求的用户代理标头。
会话过期
默认情况下,会话在 7 天后过期。但是每当会话被使用并且达到 updateAge 时,会话过期时间将更新为当前时间加上 expiresIn 值。
您可以通过将 session 对象传递给 auth 配置来更改 expiresIn 和 updateAge 值。
import { betterAuth } from "better-auth"
export const auth = betterAuth({
//... other config options
session: {
expiresIn: 60 * 60 * 24 * 7, // 7 days
updateAge: 60 * 60 * 24 // 1 day (every 1 day the session expiration is updated)
}
})禁用会话刷新
您可以禁用会话刷新,这样无论 updateAge 选项如何,会话都不会被更新。
import { betterAuth } from "better-auth"
export const auth = betterAuth({
//... other config options
session: {
disableSessionRefresh: true
}
})会话新鲜度
Better Auth 中的一些端点要求会话是新鲜的。如果会话的 createdAt 在 freshAge 限制内,则会话被视为新鲜的。默认情况下,freshAge 设置为1 天 (60 * 60 * 24)。
您可以通过在 auth 配置中传递 session 对象来自定义 freshAge 值:
import { betterAuth } from "better-auth"
export const auth = betterAuth({
//... other config options
session: {
freshAge: 60 * 5 // 5 minutes (the session is fresh if created within the last 5 minutes)
}
})要禁用新鲜度检查,将 freshAge 设置为 0:
import { betterAuth } from "better-auth"
export const auth = betterAuth({
//... other config options
session: {
freshAge: 0 // Disable freshness check
}
})会话管理
Better Auth 提供了一组函数来管理会话。
获取会话
getSession 函数检索当前活动会话。
import { authClient } from "@/lib/client"
const { data: session } = await authClient.getSession()要了解如何自定义会话响应,请查看 自定义会话响应 部分。
使用会话
useSession 操作提供了一种响应式方式来访问当前会话。
import { authClient } from "@/lib/client"
const { data: session } = authClient.useSession()列出会话
listSessions 函数返回用户活动的会话列表。
import { authClient } from "@/lib/client"
const sessions = await authClient.listSessions()撤销会话
当用户从设备注销时,会话会自动结束。但是,您也可以从用户登录的任何设备手动结束会话。
要结束会话,请使用 revokeSession 函数。只需将会话令牌作为参数传递。
await authClient.revokeSession({
token: "session-token"
})撤销其他会话
要撤销除当前会话外的所有其他会话,您可以使用 revokeOtherSessions 函数。
await authClient.revokeOtherSessions()撤销所有会话
要撤销所有会话,您可以使用 revokeSessions 函数。
await authClient.revokeSessions()在更改密码时撤销会话
当用户更改密码时,您可以通过在 changePassword 函数中将 revokeOtherSessions 设置为 true 来撤销所有会话。
await authClient.changePassword({
newPassword: newPassword,
currentPassword: currentPassword,
revokeOtherSessions: true,
})会话缓存
Cookie 缓存
每次调用 useSession 或 getSession 时都调用数据库并不是理想的选择,尤其是如果会话不经常更改。Cookie 缓存通过将会话数据存储在短期有效的签名 Cookie 中来处理这种情况——类似于使用刷新令牌的 JWT 访问令牌。
启用 Cookie 缓存后,服务器可以从 Cookie 本身检查会话有效性,而不必每次都访问数据库。Cookie 被签名以防止篡改,并且短期的 maxAge 确保会话数据定期刷新。如果会话被撤销或过期,Cookie 将自动失效。
要开启 Cookie 缓存,只需在您的 auth 配置中设置 session.cookieCache:
import { betterAuth } from "better-auth"
export const auth = betterAuth({
session: {
cookieCache: {
enabled: true,
maxAge: 5 * 60 // Cache duration in seconds
}
}
});如果您想在获取会话时禁用从 Cookie 缓存返回,您可以传递 disableCookieCache:true,这将强制服务器从数据库获取会话并刷新 Cookie 缓存。
const session = await authClient.getSession({ query: {
disableCookieCache: true
}})或在服务器端
await auth.api.getSession({
query: {
disableCookieCache: true,
},
headers: req.headers, // pass the headers
});自定义会话响应
当您调用 getSession 或 useSession 时,会话数据作为 user 和 session 对象返回。您可以使用 customSession 插件来自定义此响应。
import { customSession } from "better-auth/plugins";
export const auth = betterAuth({
plugins: [
customSession(async ({ user, session }) => {
const roles = findUserRoles(session.session.userId);
return {
roles,
user: {
...user,
newField: "newField",
},
session
};
}),
],
});这将向会话响应添加 roles 和 user.newField。
在客户端推断
import { customSessionClient } from "better-auth/client/plugins";
import type { auth } from "@/lib/auth"; // Import the auth instance as a type
const authClient = createAuthClient({
plugins: [customSessionClient<typeof auth>()],
});
const { data } = authClient.useSession();
const { data: sessionData } = await authClient.getSession();
// data.roles
// data.user.newField自定义会话响应的注意事项
- 传递给回调的
session对象不会推断插件添加的字段。
但是,作为一种变通方法,您可以拉取您的 auth 选项并将其传递给插件以推断字段。
import { betterAuth, BetterAuthOptions } from "better-auth";
const options = {
//...config options
plugins: [
//...plugins
]
} satisfies BetterAuthOptions;
export const auth = betterAuth({
...options,
plugins: [
...(options.plugins ?? []),
customSession(async ({ user, session }, ctx) => {
// now both user and session will infer the fields added by plugins and your custom fields
return {
user,
session
}
}, options), // pass options here
]
})- 当您的服务器和客户端代码位于单独的项目或仓库中,并且您无法将
auth实例作为类型引用导入时,客户端自定义会话字段的类型推断将不起作用。 - 会话缓存,包括二级存储或 Cookie 缓存,不包括自定义字段。每次获取会话时,都会调用您的自定义会话函数。
变异 list-device-sessions 端点
来自 multi-session 插件的 /multi-session/list-device-sessions 端点用于列出用户登录的设备。
您可以通过将 shouldMutateListDeviceSessionsEndpoint 选项传递给 customSession 插件来变异此端点的响应。
默认情况下,我们不变异此端点的响应。
import { customSession } from "better-auth/plugins";
export const auth = betterAuth({
plugins: [
customSession(async ({ user, session }, ctx) => {
return {
user,
session
}
}, {}, { shouldMutateListDeviceSessionsEndpoint: true }),
],
});