Strapi V4忘记密码API定制:替换验证码为4位唯一数字
在Strapi V4中自定义忘记密码API的4位数字验证码
实现步骤
1. 生成4位唯一数字验证码的工具函数
在src/utils/generate-otp.js中创建工具函数,确保生成的验证码在有效期内唯一:
const { strapi } = require('@strapi/strapi'); module.exports = async () => { // 生成4位随机数字 let otp = Math.floor(1000 + Math.random() * 9000).toString(); // 检查有效期内是否存在重复验证码 const existingToken = await strapi.db.query('plugin::users-permissions.reset-password-token').findOne({ where: { token: otp, expires_at: { $gt: new Date() } } }); // 重复则递归生成新验证码 if (existingToken) { return module.exports(); } return otp; };
2. 覆盖Users-Permissions插件的Auth服务
在src/extensions/users-permissions/server/services/auth.js中创建自定义服务,替换默认的验证码生成逻辑:
const { validateForgotPassword } = require('@strapi/plugin-users-permissions/server/validators/auth'); const generateOTP = require('../../../../utils/generate-otp'); module.exports = (plugin) => { // 覆盖忘记密码处理方法 plugin.forgotPassword = async (ctx) => { const { email } = ctx.request.body; await validateForgotPassword(ctx.request.body); const user = await strapi.db.query('plugin::users-permissions.user').findOne({ where: { email }, }); if (!user) { return ctx.send({ ok: true }); // 避免泄露用户存在性 } // 生成4位唯一验证码 const otp = await generateOTP(); // 设置1小时有效期(与默认保持一致) const expiresAt = new Date(); expiresAt.setHours(expiresAt.getHours() + 1); // 删除用户旧的重置令牌 await strapi.db.query('plugin::users-permissions.reset-password-token').deleteMany({ where: { user: user.id } }); // 保存新的验证码记录 await strapi.db.query('plugin::users-permissions.reset-password-token').create({ data: { user: user.id, token: otp, expires_at: expiresAt } }); // 发送包含验证码的邮件 await strapi.plugin('users-permissions').service('user').sendResetPasswordEmail(user, otp); return ctx.send({ ok: true }); }; return plugin; };
3. 修改重置密码邮件模板
在src/extensions/users-permissions/server/templates/reset-password.html创建自定义邮件模板,替换默认的长令牌展示:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>重置密码</title> </head> <body> <p>您好 <%= user.username %>!</p> <p>您申请重置密码,请使用以下4位验证码完成操作:</p> <p><strong><%= token %></strong></p> <p>验证码1小时内有效。</p> <p>若非您本人操作,请忽略此邮件。</p> </body> </html>
4. 适配邮件发送逻辑(可选)
如果需要自定义邮件发送细节,在src/extensions/users-permissions/server/services/user.js中覆盖发送方法:
module.exports = (plugin) => { plugin.sendResetPasswordEmail = async (user, token) => { const settings = await strapi.plugin('users-permissions').service('settings').getSettings('email'); const subject = settings.reset_password.subject || '重置密码'; const html = await strapi.plugin('users-permissions').service('email').render('reset-password', { user, token, }); await strapi.plugin('email').service('email').send({ to: user.email, from: settings.reset_password.from || settings.default.from, replyTo: settings.reset_password.replyTo || settings.default.replyTo, subject, html, }); }; return plugin; };
注意事项
- 修改完成后重启Strapi服务,确保自定义扩展生效
- 测试时需验证验证码的唯一性,避免同一时段出现重复码
- 可通过调整
expiresAt的计算逻辑修改验证码有效期
内容的提问来源于stack exchange,提问作者Tayyab Shahzad
相关产品推荐
相关产品推荐

