如何在Firebase Login Activity生成OTP前检查手机号是否已注册,未注册则跳转Signup Activity?
Hey there! Let's walk through how to implement this check before sending the OTP in your Firebase Login Activity. I'll cover two common approaches, depending on your security needs.
Firebase Auth doesn't have a direct client API to check registered phone numbers, so we'll store each user's phone number in Firestore when they sign up, then query that collection during login.
Step 1: Store Phone Numbers During Signup
After a user successfully signs up and verifies their OTP, save their phone number to a Firestore users collection. Make sure the format matches what users will input in the login screen (e.g., include country code like +1234567890):
// Assuming you've already created the FirebaseUser after OTP verification val db = FirebaseFirestore.getInstance() val userProfile = hashMapOf( "phoneNumber" to firebaseUser.phoneNumber, "uid" to firebaseUser.uid ) // Save to Firestore using the user's UID as the document ID db.collection("users").document(firebaseUser.uid).set(userProfile)
Don't forget to lock down your Firestore security rules to prevent unauthorized access:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /users/{userId} { allow read: if request.auth != null; // Only authenticated users can read allow write: if request.auth.uid == userId; // Only the user can update their own data } } }
Step 2: Check the Phone Number in Login Activity
When the user taps "Get OTP", first query Firestore to see if the number exists:
val inputPhone = phoneInputEditText.text.toString().trim() val db = FirebaseFirestore.getInstance() // Query for any user with the input phone number db.collection("users") .whereEqualTo("phoneNumber", inputPhone) .get() .addOnSuccessListener { snapshot -> if (snapshot.isEmpty) { // No matching user found — send to Signup Activity startActivity(Intent(this@LoginActivity, SignupActivity::class.java)) finish() // Optional: Prevent users from navigating back to login } else { // Number is registered — proceed with OTP generation sendOTP(inputPhone) } } .addOnFailureListener { error -> // Handle network errors or query failures Toast.makeText(this, "Failed to check number: ${error.message}", Toast.LENGTH_SHORT).show() }
Pro tip: Use a library like libphonenumber-android to standardize phone number formats (e.g., auto-add country codes, remove spaces) so your queries always match the stored values.
For stricter security (to prevent clients from tampering with query logic), use a Cloud Function that calls Firebase Admin SDK's getUserByPhoneNumber method.
Step 1: Write the Cloud Function
Initialize Cloud Functions in your project, then create an HTTPS callable function:
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); exports.checkPhoneRegistered = functions.https.onCall(async (data, context) => { const phoneNumber = data.phoneNumber; try { // Admin SDK will throw an error if the number isn't registered await admin.auth().getUserByPhoneNumber(phoneNumber); return { isRegistered: true }; } catch (err) { if (err.code === "auth/user-not-found") { return { isRegistered: false }; } // Re-throw other errors to notify the client throw new functions.https.HttpsError("internal", "Error verifying number", err); } });
Deploy it with: firebase deploy --only functions
Step 2: Call the Function from Login Activity
Invoke the cloud function to check the phone number before sending OTP:
val inputPhone = phoneInputEditText.text.toString().trim() val functions = FirebaseFunctions.getInstance() functions.getHttpsCallable("checkPhoneRegistered") .call(hashMapOf("phoneNumber" to inputPhone)) .addOnSuccessListener { result -> val isRegistered = result.data as Boolean if (!isRegistered) { startActivity(Intent(this@LoginActivity, SignupActivity::class.java)) finish() } else { sendOTP(inputPhone) } } .addOnFailureListener { error -> Toast.makeText(this, "Check failed: ${error.message}", Toast.LENGTH_SHORT).show() }
This method is more secure because the verification happens server-side, so clients can't bypass the check.
- Format Consistency: Always use the same phone number format (e.g., with country code, no special characters) across signup and login.
- Error Handling: Don't skip error handling — network drops or Firebase issues can happen, so give users clear feedback.
- Privacy Compliance: Make sure you're allowed to store user phone numbers under your region's privacy laws (like GDPR).
内容的提问来源于stack exchange,提问作者Maximus

