速率限制
Better Auth 包含一个内置的速率限制器,以帮助管理流量并防止滥用。默认情况下,在生产模式下,速率限制器设置为:
- Window: 60 seconds
- Max Requests: 100 requests
使用 auth.api 发出的服务器端请求不受速率限制影响。速率限制仅适用于客户端发起的请求。
您可以通过将 rateLimit 对象传递给 betterAuth 函数来轻松自定义这些设置。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
rateLimit: {
window: 10, // 时间窗口(秒)
max: 100, // 窗口内的最大请求数
},
})速率限制在开发模式下默认禁用。要启用它,请将 enabled 设置为 true:
export const auth = betterAuth({
rateLimit: {
enabled: true,
//...其他选项
},
})除了默认设置外,Better Auth 还为特定路径提供自定义规则。例如:
/sign-in/email:在 10 秒内限制为 3 个请求。
此外,插件也为特定路径定义自定义规则。例如,twoFactor 插件有自定义规则:
/two-factor/verify:在 10 秒内限制为 3 个请求。
这些自定义规则确保敏感操作受到更严格限制的保护。
配置速率限制
连接 IP 地址
速率限制使用连接的 IP 地址来跟踪用户发出的请求数量。默认检查的标头是 x-forwarded-for,这在生产环境中常用。如果您使用不同的标头来跟踪用户的 IP 地址,则需要指定它。
export const auth = betterAuth({
//...其他选项
advanced: {
ipAddress: {
ipAddressHeaders: ["cf-connecting-ip"], // Cloudflare 特定标头示例
},
},
rateLimit: {
enabled: true,
window: 60, // 时间窗口(秒)
max: 100, // 窗口内的最大请求数
},
})速率限制窗口
import { betterAuth } from "better-auth";
export const auth = betterAuth({
//...其他选项
rateLimit: {
window: 60, // 时间窗口(秒)
max: 100, // 窗口内的最大请求数
},
})您还可以为特定路径传递自定义规则。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
//...其他选项
rateLimit: {
window: 60, // 时间窗口(秒)
max: 100, // 窗口内的最大请求数
customRules: {
"/sign-in/email": {
window: 10,
max: 3,
},
"/two-factor/*": async (request)=> {
// 自定义函数,返回速率限制窗口和最大值
return {
window: 10,
max: 3,
}
}
},
},
})如果您想为特定路径禁用速率限制,可以将其设置为 false,或从自定义规则函数中返回 false。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
//...其他选项
rateLimit: {
customRules: {
"/get-session": false,
},
},
})存储
默认情况下,速率限制数据存储在内存中,这可能不适合许多用例,尤其是在无服务器环境中。为解决此问题,您可以使用数据库、次要存储或自定义存储来存储速率限制数据。
使用数据库
import { betterAuth } from "better-auth";
export const auth = betterAuth({
//...其他选项
rateLimit: {
storage: "database",
modelName: "rateLimit", //可选,默认使用 "rateLimit"
},
})请确保运行 migrate 以在数据库中创建速率限制表。
npx @better-auth/cli migrate使用次要存储
如果已配置 Secondary Storage,您可以使用它来存储速率限制数据。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
//...其他选项
rateLimit: {
storage: "secondary-storage"
},
})自定义存储
如果上述解决方案都不适合您的用例,您可以实现 customStorage。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
//...其他选项
rateLimit: {
customStorage: {
get: async (key) => {
// 获取速率限制数据
},
set: async (key, value) => {
// 设置速率限制数据
},
},
},
})处理速率限制错误
当请求超过速率限制时,Better Auth 返回以下标头:
X-Retry-After:用户可以发出另一个请求的秒数。
要在客户端处理速率限制错误,您可以全局处理或按请求处理。由于 Better Auth 客户端基于 Better Fetch,您可以传递 fetchOptions 来处理速率限制错误。
全局处理
import { createAuthClient } from "better-auth/client";
export const authClient = createAuthClient({
fetchOptions: {
onError: async (context) => {
const { response } = context;
if (response.status === 429) {
const retryAfter = response.headers.get("X-Retry-After");
console.log(`速率限制已超过。请在 ${retryAfter} 秒后重试`);
}
},
}
})按请求处理
import { authClient } from "./auth-client";
await authClient.signIn.email({
fetchOptions: {
onError: async (context) => {
const { response } = context;
if (response.status === 429) {
const retryAfter = response.headers.get("X-Retry-After");
console.log(`速率限制已超过。请在 ${retryAfter} 秒后重试`);
}
},
}
})Schema
如果您使用数据库存储速率限制数据,则需要此 schema:
Table Name: rateLimit
| Field Name | Type | Key | Description |
|---|---|---|---|
| id | string | 数据库 ID | |
| key | string | - | 每个速率限制键的唯一标识符 |
| count | integer | - | 时间窗口(秒) |
| lastRequest | bigint | - | 窗口内的最大请求数 |