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

在React Native EXPO应用中实现OTP验证流程的技术咨询

手机号OTP身份验证功能实现指南

整体实现流程

  • 用户在前端输入手机号,前端做格式校验后提交到后端
  • 后端生成6位随机OTP,设置5-15分钟的有效时长,将手机号和OTP、过期时间绑定存入缓存
  • 后端调用短信服务接口,把OTP下发到用户输入的手机号
  • 用户收到短信后在前端输入OTP,提交到后端校验接口
  • 后端校验手机号对应OTP是否正确且未过期,校验通过后生成设备身份凭证返回给前端,存入设备本地存储完成身份绑定

核心模块实现要点

前端侧实现

  • 手机号输入校验:如果是国内手机号可以用正则^1[3-9]\d{9}$做前置校验,适配其他地区手机号修改对应正则规则即可,避免无效请求
  • 提交按钮防重复点击:点击后设置60s倒计时,防止重复触发短信发送
  • OTP输入框优化:可以做6个独立输入框自动跳转,提升输入体验
  • 设备标识采集:校验OTP通过后,可以采集设备UA、设备指纹等信息和身份凭证绑定,后续请求携带凭证即可识别身份

前端基础逻辑示例:

// 手机号格式校验函数
function validatePhone(phone) {
  const reg = /^1[3-9]\d{9}$/
  return reg.test(phone)
}

// 发送OTP按钮倒计时逻辑
let countDown = 60
function startCountDown(btnDom) {
  btnDom.disabled = true
  const timer = setInterval(() => {
    countDown--
    btnDom.innerText = `重新发送(${countDown}s)`
    if(countDown <= 0) {
      clearInterval(timer)
      btnDom.disabled = false
      btnDom.innerText = '发送验证码'
      countDown = 60
    }
  }, 1000)
}

后端侧实现

  • OTP生成规则:生成6位纯数字即可,不要使用复杂字符,降低用户输入成本
  • 存储规则:优先使用Redis缓存存储,key设置为sms:otp:${手机号},value存储OTP值和过期时间,设置过期时间和业务有效期一致,自动清理失效数据
  • 频率限制:同一个手机号1分钟内最多发送1次,1小时内最多发送5次,防止恶意刷短信
  • 校验逻辑:校验通过后立即删除对应的Redis缓存,避免同一个OTP被重复校验
  • 身份凭证生成:校验通过后生成包含用户手机号、设备信息、过期时间的JWT或者SessionId,返回给前端,后续接口请求携带该凭证即可完成身份校验

后端基础逻辑示例(Python+Flask):

import random
import redis
from flask import Flask, request, jsonify
import jwt
import datetime

app = Flask(__name__)
redis_client = redis.Redis(host='localhost', port=6379, db=0)
JWT_SECRET = '你的自定义密钥'

# 发送OTP接口
@app.route('/send_otp', methods=['POST'])
def send_otp():
    phone = request.json.get('phone')
    # 先校验发送频率
    freq_key = f'sms:freq:{phone}'
    if redis_client.get(freq_key):
        return jsonify({'code': 400, 'msg': '请求过于频繁,请稍后再试'})
    # 生成6位OTP
    otp = random.randint(100000, 999999)
    # 存储OTP,有效期10分钟
    otp_key = f'sms:otp:{phone}'
    redis_client.setex(otp_key, 60*10, str(otp))
    # 设置频率限制:1分钟1次
    redis_client.setex(freq_key, 60, '1')
    # 这里调用你对接的短信服务商发送接口
    # sms_service.send(phone, f'您的验证码是{otp},10分钟内有效')
    return jsonify({'code': 200, 'msg': '验证码发送成功'})

# 校验OTP接口
@app.route('/verify_otp', methods=['POST'])
def verify_otp():
    phone = request.json.get('phone')
    input_otp = request.json.get('otp')
    device_info = request.headers.get('User-Agent')
    otp_key = f'sms:otp:{phone}'
    stored_otp = redis_client.get(otp_key)
    if not stored_otp or stored_otp.decode() != input_otp:
        return jsonify({'code': 400, 'msg': '验证码错误或已过期'})
    # 校验通过立即删除OTP
    redis_client.delete(otp_key)
    # 生成JWT凭证,有效期7天
    token = jwt.encode({
        'phone': phone,
        'device': device_info,
        'exp': datetime.datetime.utcnow() + datetime.timedelta(days=7)
    }, JWT_SECRET, algorithm='HS256')
    return jsonify({'code': 200, 'msg': '验证成功', 'token': token})

注意事项

  • 不要把OTP明文返回给前端,所有生成和校验逻辑都放在后端处理
  • 生产环境要给短信接口加签名校验,防止恶意调用刷短信
  • OTP有效期不要超过15分钟,降低被盗用风险
  • 流量较大的场景可以增加图形验证码作为前置校验,进一步防止恶意刷取短信

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 15:36:00