速率限制

Better Auth 内置了速率限制器,用于管理流量和防止滥用。在生产模式下,默认设置为:

  • 时间窗口:60 秒
  • 最大请求数:100 次请求

使用 auth.api 发起的服务器端请求不受速率限制影响。速率限制仅适用于客户端发起的请求。

您可以通过将 rateLimit 对象传递给 betterAuth 函数来轻松自定义这些设置。

auth.ts
import { betterAuth } from "better-auth";

export const auth = betterAuth({
    rateLimit: {
        window: 10, // 时间窗口(秒)
        max: 100, // 窗口内的最大请求数
    },
})

在开发模式下,默认禁用速率限制。要启用它,请将 enabled 设置为 true

auth.ts
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 地址,则需要指定它。

auth.ts
export const auth = betterAuth({
    //...其他选项
    advanced: {
        ipAddress: {
          ipAddressHeaders: ["cf-connecting-ip"], // Cloudflare 特定请求头示例
      },
    },
    rateLimit: {
        enabled: true,
        window: 60, // 时间窗口(秒)
        max: 100, // 窗口内的最大请求数
    },
})

速率限制窗口

auth.ts
import { betterAuth } from "better-auth";

export const auth = betterAuth({
    //...其他选项
    rateLimit: {
        window: 60, // 时间窗口(秒)
        max: 100, // 窗口内的最大请求数
    },
})

您还可以为特定路径传递自定义规则。

auth.ts
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,
                }
            }
        },
    },
})

存储

默认情况下,速率限制数据存储在内存中,这可能不适用于许多用例,尤其是在无服务器环境中。为了解决这个问题,您可以使用数据库、辅助存储或自定义存储来存储速率限制数据。

使用数据库

auth.ts
import { betterAuth } from "better-auth";

export const auth = betterAuth({
    //...其他选项
    rateLimit: {
        storage: "database",
        modelName: "rateLimit", //可选,默认为 "rateLimit"
    },
})

确保运行 migrate 命令在数据库中创建速率限制表。

npx @better-auth/cli migrate

使用二级存储

如果已配置二级存储,可以使用它来存储速率限制数据。

auth.ts
import { betterAuth } from "better-auth";

export const auth = betterAuth({
    //...其他选项
    rateLimit: {
		storage: "secondary-storage"
    },
})

自定义存储

如果以上解决方案都不符合您的使用场景,可以实现 customStorage

auth.ts
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 来处理速率限制错误。

全局处理

auth-client.ts
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} 秒后重试`);
            }
        },
    }
})

按请求处理

auth-client.ts
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} 秒后重试`);
            }
        },
    }
})

数据表结构

如果您使用数据库存储频率限制数据,需要以下数据表结构:

表名:rateLimit

字段名称类型Key描述
idstring数据库ID
keystring-每个频率限制键的唯一标识符
countinteger-时间窗口(秒)
lastRequestbigint-窗口内的最大请求数

On this page