🚀 快速安装

复制以下命令并运行,立即安装此 Skill:

npx skills add https://github.com/better-auth/skills --skill email-and-password-best-practices

💡 提示:需要 Node.js 和 NPM

快速开始

  1. 启用邮箱/密码:emailAndPassword: { enabled: true }
  2. 配置 emailVerification.sendVerificationEmail
  3. 添加 sendResetPassword 用于密码重置流程
  4. 运行 npx @better-auth/cli@latest migrate
  5. 验证:尝试注册并确认验证邮件被触发

邮箱验证设置

配置 emailVerification.sendVerificationEmail 以验证用户的邮箱地址。

import { betterAuth } from "better-auth";
import { sendEmail } from "./email"; // 你的邮件发送函数

export const auth = betterAuth({
  emailVerification: {
    sendVerificationEmail: async ({ user, url, token }, request) => {
      await sendEmail({
        to: user.email,
        subject: "验证您的邮箱地址",
        text: `点击此链接验证您的邮箱:${url}`,
      });
    },
  },
});

注意url 参数包含完整的验证链接。如果您需要构建自定义验证 URL,可以使用 token

要求邮箱验证

为了更严格的安全性,启用 emailAndPassword.requireEmailVerification 以阻止用户登录,直到他们验证其邮箱。启用后,未验证的用户每次尝试登录时都会收到新的验证邮件。

export const auth = betterAuth({
  emailAndPassword: {
    requireEmailVerification: true,
  },
});

注意:这要求配置好 sendVerificationEmail,并且仅适用于邮箱/密码登录。

客户端验证

实现客户端验证以获得即时用户反馈并减少服务器负载。

回调 URL

在注册和登录请求的回调 URL 中始终使用绝对 URL(包含源)。这可以防止 Better Auth 需要推断源,从而避免在后端和前端位于不同域时出现问题。

const { data, error } = await authClient.signUp.email({
  callbackURL: "https://example.com/callback", // 包含源的绝对 URL
});

密码重置流程

在邮箱和密码配置中提供 sendResetPassword 以启用密码重置。

import { betterAuth } from "better-auth";
import { sendEmail } from "./email"; // 你的邮件发送函数

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    // 发送重置密码邮件的自定义邮件发送函数
    sendResetPassword: async ({ user, url, token }, request) => {
      void sendEmail({
        to: user.email,
        subject: "重置您的密码",
        text: `点击此链接重置您的密码:${url}`,
      });
    },
    // 可选的事件钩子
    onPasswordReset: async ({ user }, request) => {
      // 你的逻辑
      console.log(`用户 ${user.email} 的密码已重置。`);
    },
  },
});

安全考虑

内置保护:后台邮件发送(防止计时攻击)、对无效请求进行虚拟操作、无论用户是否存在都返回一致响应消息。

在无服务器平台上,配置后台任务处理器:

export const auth = betterAuth({
  advanced: {
    backgroundTasks: {
      handler: (promise) => {
        // 使用特定平台的方法,如 waitUntil
        waitUntil(promise);
      },
    },
  },
});

令牌安全

默认情况下,令牌在 1 小时后过期。使用 resetPasswordTokenExpiresIn(以秒为单位)进行配置:

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    resetPasswordTokenExpiresIn: 60 * 30, // 30 分钟
  },
});

令牌为一次性使用 — 成功重置后立即删除。

会话撤销

启用 revokeSessionsOnPasswordReset 可在密码重置时使所有现有会话失效:

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    revokeSessionsOnPasswordReset: true,
  },
});

密码要求

密码长度限制(可配置):

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    minPasswordLength: 12,
    maxPasswordLength: 256,
  },
});

发送密码重置

调用 requestPasswordReset 发送重置链接。这将触发配置中的 sendResetPassword 函数。

const data = await auth.api.requestPasswordReset({
  body: {
    email: "john.doe@example.com", // 必需
    redirectTo: "https://example.com/reset-password",
  },
});

或使用 authClient:

const { data, error } = await authClient.requestPasswordReset({
  email: "john.doe@example.com", // 必需
  redirectTo: "https://example.com/reset-password",
});

注意:虽然 email 是必需的,但我们也建议配置 redirectTo 以获得更流畅的用户体验。

密码哈希

默认:scrypt(Node.js 原生,无外部依赖)。

自定义哈希算法

要使用 Argon2id 或其他算法,请提供自定义的 hashverify 函数:

import { betterAuth } from "better-auth";
import { hash, verify, type Options } from "@node-rs/argon2";

const argon2Options: Options = {
  memoryCost: 65536, // 64 MiB
  timeCost: 3, // 3 次迭代
  parallelism: 4, // 4 条并行道
  outputLen: 32, // 32 字节输出
  algorithm: 2, // Argon2id 变体
};

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    password: {
      hash: (password) => hash(password, argon2Options),
      verify: ({ password, hash: storedHash }) =>
        verify(storedHash, password, argon2Options),
    },
  },
});

注意:如果您在现有系统上切换哈希算法,使用旧算法哈希密码的用户将无法登录。如果需要,请规划迁移策略。

📄 原始文档

完整文档(英文):

https://skills.sh/better-auth/skills/email-and-password-best-practices

💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。