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

Android应用Firebase邮箱认证与手机号二次验证集成方法问询

我刚好做过类似的集成,给你梳理一套完整的可落地方案,一步步来就很清晰:

集成Firebase邮箱密码+手机号双重认证的完整方案

一、前期准备

  • 确保你的Firebase项目已经启用了邮箱/密码认证和手机号认证(在Firebase控制台的Authentication>Sign-in method里开启)
  • 提前规划用户数据存储:把用户的手机号、2FA启用状态(比如is2FAEnabled)绑定到已有邮箱账号,建议存在Firestore的用户专属文档里,或者Firebase Auth的用户自定义字段中

二、核心登录流程设计

用户的完整登录路径应该是:

  1. 用户输入邮箱+密码,完成Firebase邮箱密码基础登录
  2. 登录成功后,检查该用户是否开启了2FA
  3. 未开启2FA:直接进入应用主界面
  4. 已开启2FA:触发手机号验证码验证流程,验证通过后方可进入主界面

三、具体代码实现步骤

1. 保留原有邮箱密码登录逻辑

// 邮箱密码登录核心代码
val emailInput = binding.etEmail.text.toString()
val passwordInput = binding.etPassword.text.toString()

FirebaseAuth.getInstance().signInWithEmailAndPassword(emailInput, passwordInput)
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            val currentUser = FirebaseAuth.getInstance().currentUser
            // 登录成功后立即检查2FA状态
            checkUser2FAStatus(currentUser)
        } else {
            Toast.makeText(this, "登录失败:${task.exception?.message}", Toast.LENGTH_SHORT).show()
        }
    }

2. 检查用户2FA启用状态

这里以Firestore存储用户数据为例:

private fun checkUser2FAStatus(user: FirebaseUser?) {
    user ?: return
    val db = FirebaseFirestore.getInstance()
    db.collection("users").document(user.uid)
        .get()
        .addOnSuccessListener { doc ->
            val is2FAEnabled = doc.getBoolean("is2FAEnabled") ?: false
            val boundPhone = doc.getString("boundPhone") ?: ""
            
            if (is2FAEnabled && boundPhone.isNotEmpty()) {
                // 启动手机号验证码验证流程
                triggerPhoneVerification(boundPhone)
            } else {
                // 直接进入主界面
                startActivity(Intent(this, MainActivity::class.java))
                finish()
            }
        }
}

3. 手机号验证码验证流程(关键集成点)

这里不需要用手机号登录,而是用Firebase的PhoneAuthProvider完成验证码的发送与验证,核心是验证用户对绑定手机号的所有权:

private lateinit var verificationId: String
private lateinit var resendToken: PhoneAuthProvider.ForceResendingToken

// 发送验证码到用户绑定的手机号
private fun triggerPhoneVerification(phoneNumber: String) {
    val options = PhoneAuthOptions.newBuilder(FirebaseAuth.getInstance())
        .setPhoneNumber(phoneNumber)       // 必须带国家码,比如+86138xxxxxxx
        .setTimeout(60L, TimeUnit.SECONDS) // 验证码有效期
        .setActivity(this)                 // 当前上下文Activity
        .setCallbacks(object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            override fun onVerificationCompleted(credential: PhoneAuthCredential) {
                // 自动验证成功(比如可信设备),直接完成验证
                verifyPhoneCredential(credential)
            }

            override fun onVerificationFailed(e: FirebaseException) {
                Toast.makeText(this@LoginActivity, "验证码发送失败:${e.message}", Toast.LENGTH_SHORT).show()
            }

            override fun onCodeSent(id: String, token: PhoneAuthProvider.ForceResendingToken) {
                // 验证码发送成功,保存凭证用于后续验证
                verificationId = id
                resendToken = token
                // 弹出验证码输入框或跳转到验证页面
                showCodeInputDialog()
            }
        })
        .build()
    PhoneAuthProvider.verifyPhoneNumber(options)
}

// 验证验证码凭证
private fun verifyPhoneCredential(credential: PhoneAuthCredential) {
    FirebaseAuth.getInstance().signInWithCredential(credential)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                // 手机号验证通过,进入主界面
                startActivity(Intent(this, MainActivity::class.java))
                finish()
            } else {
                Toast.makeText(this, "验证码错误,请重新输入", Toast.LENGTH_SHORT).show()
            }
        }
}

// 用户手动输入验证码后的验证逻辑
private fun verifyUserInputCode(inputCode: String) {
    val credential = PhoneAuthProvider.getCredential(verificationId, inputCode)
    verifyPhoneCredential(credential)
}

4. 用户启用2FA的设置逻辑(补充)

在应用设置页面,需要让用户先绑定手机号并验证,再开启2FA:

// 用户在设置页开启2FA的逻辑
fun enableUser2FA(phoneNumber: String) {
    // 先验证手机号有效性
    triggerPhoneVerification(phoneNumber)
    // 验证成功后更新用户的2FA状态
    val currentUser = FirebaseAuth.getInstance().currentUser ?: return
    FirebaseFirestore.getInstance().collection("users").document(currentUser.uid)
        .update(mapOf(
            "is2FAEnabled" to true,
            "boundPhone" to phoneNumber
        ))
        .addOnSuccessListener {
            Toast.makeText(this, "双重认证已成功启用", Toast.LENGTH_SHORT).show()
        }
}

四、关键注意事项

  • 手机号格式必须规范:必须包含国家码(如+86),否则Firebase会拒绝发送验证码
  • 要提供验证码重发功能:利用之前保存的resendToken调用PhoneAuthProvider.verifyPhoneNumber时传入即可
  • 可选优化:验证成功后可标记当前设备为可信设备,下次登录无需验证(可在用户文档中存储设备ID列表)
  • 安全规则:Firestore的用户文档要设置严格的安全规则,确保只有用户本人能读取和修改自己的2FA状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:27:00