电话号码
手机号插件扩展了认证系统,允许用户使用手机号进行登录和注册。它包含 OTP(一次性密码)功能来验证手机号。
安装
在服务端添加插件
import { betterAuth } from "better-auth"
import { phoneNumber } from "better-auth/plugins"
const auth = betterAuth({
plugins: [
phoneNumber({
sendOTP: ({ phoneNumber, code }, request) => {
// 实现通过短信发送 OTP 验证码
}
})
]
})
迁移数据库
运行迁移或生成模式,以向数据库添加必要的字段和表。
npx @better-auth/cli migrate
npx @better-auth/cli generate
请参阅 Schema 部分以手动添加字段。
添加客户端插件
import { createAuthClient } from "better-auth/client"
import { phoneNumberClient } from "better-auth/client/plugins"
const authClient = createAuthClient({
plugins: [
phoneNumberClient()
]
})
使用方法
发送验证码进行验证
要向用户的手机号发送验证码进行验证,可以使用 sendVerificationCode
端点。
const { data, error } = await authClient.phoneNumber.sendOtp({ phoneNumber: "+1234567890", // required});
属性 | 描述 | 类型 |
---|---|---|
phoneNumber | 要发送验证码的手机号 | string |
验证手机号
验证码发送后,用户可以通过提供验证码来验证其手机号。
const { data, error } = await authClient.phoneNumber.verify({ phoneNumber: "+1234567890", // required code: "123456", // required disableSession: false, updatePhoneNumber: true,});
属性 | 描述 | 类型 |
---|---|---|
phoneNumber | 要验证的手机号 | string |
code | 验证码 | string |
disableSession? | 验证后禁用会话创建 | boolean |
updatePhoneNumber? | 检查是否存在会话并更新手机号 | boolean |
当手机号验证成功后,用户表中的 phoneNumberVerified
字段将被设置为 true
。如果 disableSession
未设置为 true
,系统将为用户创建一个会话。此外,如果提供了 callbackOnVerification
,该回调将被调用。
允许使用手机号注册
要允许用户使用手机号注册,您可以在插件配置中传递 signUpOnVerification
选项。这需要您传递 getTempEmail
函数来为用户生成临时邮箱。
export const auth = betterAuth({
plugins: [
phoneNumber({
sendOTP: ({ phoneNumber, code }, request) => {
// 实现通过短信发送验证码
},
signUpOnVerification: {
getTempEmail: (phoneNumber) => {
return `${phoneNumber}@my-site.com`
},
// 可选,您也可以传递 `getTempName` 函数来为用户生成临时名称
getTempName: (phoneNumber) => {
return phoneNumber // 默认情况下,将使用手机号作为名称
}
}
})
]
})
使用手机号登录
除了使用发送-验证流程登录用户外,您还可以将手机号作为标识符,使用手机号和密码登录用户。
const { data, error } = await authClient.signIn.phoneNumber({ phoneNumber: "+1234567890", // required password, // required rememberMe: true,});
属性 | 描述 | 类型 |
---|---|---|
phoneNumber | 用于登录的手机号。 | string |
password | 用于登录的密码。 | string |
rememberMe? | 记住会话。 | boolean |
更新手机号码
更新手机号码的流程与验证手机号码相同。用户将收到一个 OTP 验证码来验证新的手机号码。
await authClient.phoneNumber.sendOtp({
phoneNumber: "+1234567890" // 新的手机号码
})
然后使用 OTP 验证码验证新的手机号码。
const isVerified = await authClient.phoneNumber.verify({
phoneNumber: "+1234567890",
code: "123456",
updatePhoneNumber: true // 设置为 true 以更新手机号码
})
如果存在用户会话,手机号码将自动更新。
禁用会话创建
默认情况下,插件在验证手机号码后会为用户创建一个会话。您可以通过向 verify
方法传递 disableSession: true
来禁用此行为。
const isVerified = await authClient.phoneNumber.verify({
phoneNumber: "+1234567890",
code: "123456",
disableSession: true
})
请求密码重置
要使用 phoneNumber
发起密码重置流程,您可以首先在客户端调用 requestPasswordReset
,向用户的手机号码发送 OTP 验证码。
const { data, error } = await authClient.phoneNumber.requestPasswordReset({ phoneNumber: "+1234567890", // required});
属性 | 描述 | 类型 |
---|---|---|
phoneNumber | 与该用户关联的手机号码。 | string |
然后,您可以在客户端使用 OTP 验证码和新密码调用 resetPassword
来重置密码。
const { data, error } = await authClient.phoneNumber.resetPassword({ otp: "123456", // required phoneNumber: "+1234567890", // required newPassword: "new-and-secure-password", // required});
属性 | 描述 | 类型 |
---|---|---|
otp | 用于重置密码的一次性验证码。 | string |
phoneNumber | 需要重置密码的账户的手机号码。 | string |
newPassword | 新密码。 | string |
配置选项
otpLength
: 要生成的 OTP 验证码长度。默认值为6
。sendOTP
: 用于向用户手机号发送 OTP 验证码的函数。接收手机号和 OTP 验证码作为参数。expiresIn
: OTP 验证码的过期时间(以秒为单位)。默认值为300
秒。callbackOnVerification
: 手机号验证成功后调用的函数。第一个参数为手机号和用户对象,第二个参数为请求对象。
export const auth = betterAuth({
plugins: [
phoneNumber({
sendOTP: ({ phoneNumber, code }, request) => {
// 实现通过短信发送 OTP 验证码的逻辑
},
callbackOnVerification: async ({ phoneNumber, user }, request) => {
// 实现手机号验证成功后的回调逻辑
}
})
]
})
-
sendPasswordResetOTP
: 用于密码重置时向用户手机号发送 OTP 验证码的函数。接收手机号和 OTP 验证码作为参数。 -
phoneNumberValidator
: 自定义的手机号验证函数。接收手机号作为参数,返回布尔值表示手机号是否有效。 -
signUpOnVerification
: 包含以下属性的对象:getTempEmail
: 为用户生成临时邮箱的函数。接收手机号作为参数,返回临时邮箱地址。getTempName
: 为用户生成临时名称的函数。接收手机号作为参数,返回临时名称。
-
requireVerification
: 启用后,用户必须验证手机号才能使用手机号登录。如果未验证的用户尝试登录,服务器将返回 401 错误(PHONE_NUMBER_NOT_VERIFIED)并自动触发发送 OTP 验证码以启动验证流程。
数据库结构
该插件需要在用户表中添加 2 个字段
用户表
字段名称 | 类型 | Key | 描述 |
---|---|---|---|
phoneNumber | string | 用户的电话号码 | |
phoneNumberVerified | boolean | 电话号码是否已验证 |
OTP 验证尝试
电话号码插件内置了防止暴力破解攻击的保护机制,通过限制每个 OTP 代码的验证尝试次数来实现。
phoneNumber({
allowedAttempts: 3, // 默认为 3
// ... 其他选项
})
当用户超过允许的验证尝试次数时:
- OTP 代码将自动删除
- 进一步的验证尝试将返回 403(禁止)状态,并显示"尝试次数过多"的消息
- 用户需要请求新的 OTP 代码才能继续
超出尝试次数后的错误响应示例:
{
"error": {
"status": 403,
"message": "Too many attempts"
}
}
当收到 403 状态码时,提示用户请求新的 OTP 代码