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实现:
- 后端接收手机号请求,查询数据库获取对应的UID
- 后端用Firebase Admin SDK生成自定义token
- 客户端调用
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
相关产品推荐
相关产品推荐

