You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Strapi v4能否实现手机号验证码登录认证功能?

Strapi v4 手机号+短信验证码登录实现方案

当然可以实现,Strapi v4的扩展性完全支持手机号+短信验证码登录的需求,以下是具体实现思路和步骤:

1. 扩展用户模型

首先需要在默认的用户模型中添加手机号字段,确保手机号唯一且必填:
在src/api/user/content-types/user/schema.json中添加字段配置:

{
  "attributes": {
    "phone": {
      "type": "string",
      "unique": true,
      "required": true,
      "minLength": 11,
      "maxLength": 11
    }
  }
}

修改后重启Strapi,即可在用户管理面板中看到手机号字段。

2. 创建验证码管理模型

新建一个VerificationCode内容类型,用于存储验证码和过期时间,字段包括:

  • phone:字符串类型,关联用户手机号
  • code:字符串类型,存储6位验证码
  • expiresAt:日期时间类型,设置验证码过期时间(比如5分钟)

3. 编写自定义认证服务

在src/api/auth/services/auth.js中实现验证码生成、发送、验证逻辑:

'use strict';

module.exports = ({ strapi }) => ({
  // 生成6位随机验证码
  generateCode() {
    return Math.floor(100000 + Math.random() * 900000).toString();
  },

  // 发送短信验证码(需替换为实际短信服务商API调用)
  async sendSmsCode(phone) {
    const code = this.generateCode();
    // 示例:调用第三方短信接口发送验证码
    // await strapi.service('plugin::sms.send')(phone, `您的登录验证码是${code},5分钟内有效`);
    
    // 保存验证码到数据库
    await strapi.db.query('api::verification-code.verification-code').create({
      data: {
        phone,
        code,
        expiresAt: new Date(Date.now() + 5 * 60 * 1000)
      }
    });
    return { success: true, message: '验证码已发送' };
  },

  // 验证验证码并生成登录令牌
  async verifyCode(phone, code) {
    // 查询有效验证码
    const validCode = await strapi.db.query('api::verification-code.verification-code').findOne({
      where: {
        phone,
        code,
        expiresAt: { $gt: new Date() }
      }
    });

    if (!validCode) {
      throw new Error('验证码无效或已过期');
    }

    // 验证通过后删除验证码,防止重复使用
    await strapi.db.query('api::verification-code.verification-code').delete({
      where: { id: validCode.id }
    });

    // 查询对应用户
    const user = await strapi.db.query('plugin::users-permissions.user').findOne({
      where: { phone }
    });

    if (!user) {
      throw new Error('该手机号未注册');
    }

    // 生成Strapi标准JWT令牌
    const jwtToken = strapi.plugins['users-permissions'].services.jwt.issue({ id: user.id });
    return { success: true, user, jwt: jwtToken };
  }
});

4. 配置自定义路由

在src/api/auth/routes/auth.js中添加两个公开路由:

'use strict';

module.exports = {
  routes: [
    {
      method: 'POST',
      path: '/auth/send-sms-code',
      handler: 'auth.sendSmsCode',
      config: { auth: false }
    },
    {
      method: 'POST',
      path: '/auth/login-with-sms',
      handler: 'auth.verifyCode',
      config: { auth: false }
    }
  ]
};

5. 权限配置

在Strapi后台的「设置-权限」中,将上述两个自定义路由的权限设置为「公开」,确保未登录用户可以访问。

6. 前端对接流程

  1. 用户输入手机号,前端调用POST /auth/send-sms-code接口,传入手机号
  2. 用户收到短信后输入验证码,前端调用POST /auth/login-with-sms接口,传入手机号和验证码
  3. 接口返回JWT令牌后,前端将令牌存入本地存储,后续请求携带Authorization: Bearer {token}头即可完成认证

额外注意事项

  • 短信服务商API需自行集成,可封装为Strapi插件提升复用性
  • 高并发场景建议用Redis替代数据库存储验证码,提升性能
  • 可添加限流逻辑,限制同一手机号的验证码发送频率,防止恶意刷取短信

内容的提问来源于stack exchange,提问作者varimax

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 21:30:58