速率限制

Better Auth包含一个内置的速率限制器,用于帮助管理流量和防止滥用。默认情况下,在生产模式下,速率限制器设置为:

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

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

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

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 个请求。

这些自定义规则确保敏感操作受到更严格的限制保护。

配置速率限制

速率限制窗口

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 { client } from "./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

Field NameTypeKeyDescription
idstring数据库 ID
keystring-每个速率限制键的唯一标识符
countinteger-时间窗口(秒)
lastRequestbigint-窗口内的最大请求数

On this page