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

React Native Firebase Phone Auth:发送短信前检查用户是否已存在

嘿,我来帮你搞定这个问题!核心思路是在调用验证码发送接口前,先通过数据库查询手机号是否已注册——因为Firebase Auth本身没有提供客户端直接通过手机号查询用户的API,所以我们需要额外存储手机号和用户UID的映射关系,来实现提前校验。

第一步:存储用户手机号与UID的映射

当用户首次完成手机号认证后,把手机号和对应的UID存到Firebase Firestore(或实时数据库)里,这样后续就能快速查询手机号是否已关联账号。修改你的authenticate函数:

authenticate = async (credential) => {
  const userCredential = await firebase.auth().signInAndRetrieveDataWithCredential(credential);
  const user = userCredential.user;
  
  // 将手机号和UID写入Firestore的userPhones集合
  await firestore().collection('userPhones').doc(user.phoneNumber).set({
    uid: user.uid,
    phoneNumber: user.phoneNumber,
    createdAt: firestore.FieldValue.serverTimestamp()
  });
  
  return user;
};

第二步:修改验证码流程,先查询再发送

在调用verifyPhoneNumber前,先去Firestore查询手机号是否存在。如果存在,就跳过验证码发送逻辑(注意:这里要兼顾安全,下面会说明);如果不存在,再正常发送验证码。

修改你的confirmPhone函数:

confirmPhone = async (phoneNumber) => {
  return new Promise(async (res, rej) => {
    try {
      // 1. 先查询数据库,检查手机号是否已注册
      const phoneDoc = await firestore().collection('userPhones').doc(phoneNumber).get();
      
      if (phoneDoc.exists) {
        // 用户已存在的处理逻辑
        const currentUser = firebase.auth().currentUser;
        if (currentUser && currentUser.phoneNumber === phoneNumber) {
          // 如果用户已在当前设备登录,直接返回用户信息
          console.log('用户已登录,直接返回信息');
          res({ user: currentUser });
          return;
        } else {
          // 安全提醒:如果是新设备,跳过验证码会有风险!
          // 如果你确定要跳过,需要后端生成自定义token来登录(后面会说)
          // 这里先给出安全做法:提示用户已注册,继续发送验证码
          console.log('该手机号已注册,发送验证码登录');
        }
      }
      
      // 2. 用户未注册或需要验证,正常发送验证码
      firebase.auth().verifyPhoneNumber(phoneNumber)
        .on('state_changed', async (phoneAuthSnapshot) => {
          console.log('phoneAUTH', phoneAuthSnapshot);
          switch (phoneAuthSnapshot.state) {
            case firebase.auth.PhoneAuthState.AUTO_VERIFIED:
              console.log('PhoneAuthState.AUTO_VERIFIED', phoneAuthSnapshot);
              await this.confirmCode(phoneAuthSnapshot.verificationId, phoneAuthSnapshot.code, phoneAuthSnapshot);
              res(phoneAuthSnapshot);
              break;
            case firebase.auth.PhoneAuthState.CODE_SENT:
              console.log('code send', phoneAuthSnapshot);
              UserStore.setVerificationId(phoneAuthSnapshot.verificationId);
              res(phoneAuthSnapshot);
              break;
            case firebase.auth.PhoneAuthState.AUTO_VERIFY_TIMEOUT:
              console.log('AUTO_VERIFY_TIMEOUT', phoneAuthSnapshot);
              UserStore.setVerificationId(phoneAuthSnapshot.verificationId);
              res(phoneAuthSnapshot);
              break; // 你原来的代码这里漏了break,会导致执行到ERROR分支,已修复!
            case firebase.auth.PhoneAuthState.ERROR:
              console.log('PhoneAuthState.ERROR', phoneAuthSnapshot);
              UserStore.setErrorConfirmationCode(phoneAuthSnapshot.error);
              rej(phoneAuthSnapshot);
              break;
          }
        });
    } catch (error) {
      rej(error);
    }
  });
};

重要的安全说明

直接跳过验证码登录是有风险的——任何人输入他人手机号就能获取信息或登录账号。如果你的应用场景必须这么做(比如内部测试、信任环境),可以通过后端生成自定义token实现:

  1. 后端接收手机号请求,查询数据库获取对应的UID
  2. 后端用Firebase Admin SDK生成自定义token
  3. 客户端调用firebase.auth().signInWithCustomToken(token)直接登录,获取用户信息

额外的数据库规则配置

为了防止恶意遍历手机号,给Firestore设置安全规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /userPhones/{phoneNumber} {
      allow read: if request.auth != null; // 仅允许认证用户查询
      allow write: if request.auth != null && request.auth.token.phone_number == phoneNumber; // 仅允许用户自己写入自己的手机号
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:47:10