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

Android(Kotlin) Firebase Auth邮箱密码认证reCAPTCHA空token警告解决

问题

使用Kotlin开发Android应用时,通过Firebase Auth实现邮箱密码注册与登录,出现警告:Creating user with <email> with empty reCAPTCHA token。原本以为reCAPTCHA仅用于手机号注册,且相关文档未提及邮箱密码认证需要reCAPTCHA,虽只是警告,但想解决该问题。相关代码如下:

package com.integriapp.encuestamovilidad

import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.Firebase
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.auth


class AuthActivity : AppCompatActivity() {

    private lateinit var auth: FirebaseAuth
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_auth)
        auth = Firebase.auth
        auth.setLanguageCode("es")


        setup()
    }
    fun setup(){
        title = "Autenticación"
        val signUpBtn = findViewById<Button>(R.id.signUpBtn)
        val loginBtn = findViewById<Button>(R.id.loginBtn)
        val emailTxt = findViewById<EditText>(R.id.emailTxt)
        val passwordTxt = findViewById<EditText>(R.id.passwordTxt)

        signUpBtn.setOnClickListener {
            Log.d("EncuestaMovilidad", "setOnClickListener")
            val email = emailTxt.text.toString()
            val password = passwordTxt.text.toString()

            if (email.isEmpty() || password.isEmpty()) {
                Log.d("EncuestaMovilidad", "email and password empty")
                return@setOnClickListener
            }

            // Crear un nuevo usuario con las credenciales
            auth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener { task ->
                    if (task.isSuccessful) {
                        Log.d("EncuestaMovilidad", "SUCCESS")
                        // Navegar a la siguiente actividad o realizar acciones
                        // tras el registro exitoso
                        val uid = Firebase.auth.currentUser?.uid
                        Log.d("EncuestaMovilidad", "uid: $uid")
                        showHome(task.result.user?.email.toString(), ProviderType.BASIC)
                    } else {
                        val exception = task.exception
                        showErrorAlert("${exception?.message}")
                        Log.e("EncuestaMovilidad", "createUserWithEmail:failure", task.exception)
                    }
                }
        }

        loginBtn.setOnClickListener {
            Log.d("EncuestaMovilidad", "setOnClickListener")
            val email = emailTxt.text.toString()
            val password = passwordTxt.text.toString()

            if (email.isEmpty() || password.isEmpty()) {
                Log.d("EncuestaMovilidad", "email and password empty")
                return@setOnClickListener
            }

            // Iniciar sesión con las credenciales del usuario
            auth.signInWithEmailAndPassword(email, password)
                .addOnCompleteListener { task ->
                    if (task.isSuccessful) {
                        Log.d("EncuestaMovilidad", "SUCCESS")

                        val uid = Firebase.auth.currentUser?.uid
                        Log.d("EncuestaMovilidad", "uid: $uid")
                        showHome(task.result.user?.email.toString(), ProviderType.BASIC)
                    } else {
                        val exception = task.exception
                        showErrorAlert("${exception?.message}")
                        Log.e("EncuestaMovilidad", "signInWithEmail:failure", exception)
                    }
                }
        }

    }
    private fun showErrorAlert(msj: String) {
        try {
            val builder: AlertDialog.Builder = AlertDialog.Builder(this)
            builder
                .setTitle("Error")
                .setMessage(msj)
                .setPositiveButton("Aceptar",null)

            val dialog: AlertDialog = builder.create()
            dialog.show()
        } catch (e: Exception) {
            Log.e("AlertDialog", "Error al mostrar el diálogo de alerta:", e)
        }
    }

    private fun showHome(email: String, provider: ProviderType){
        val homeIntent = Intent(this, HomeActivity::class.java).apply {
            putExtra("Email", email)
            putExtra("Provider", provider.toString())
        }
        startActivity(homeIntent)
    }
}
解决方案

警告原因

Firebase Auth为提升账号安全性,目前对邮箱密码认证也引入了reCAPTCHA验证机制——尤其是针对未正式发布的测试应用、或存在自动化攻击风险的场景。该警告表示当前认证请求未携带reCAPTCHA token,虽暂时不影响功能,但后续若触发安全限制,可能导致认证失败。

解决步骤

  1. 获取reCAPTCHA站点密钥
    登录Firebase控制台,进入项目的「Authentication」→「登录方法」→「邮箱/密码」,在页面下方找到reCAPTCHA配置区域,获取对应的站点密钥。

  2. 集成reCAPTCHA验证到代码
    确保项目依赖的Firebase Auth SDK为最新版本,然后修改AuthActivity代码:

    • 声明FirebaseRecaptchaVerifier实例:
      private lateinit var recaptchaVerifier: FirebaseRecaptchaVerifier
      
    • 在onCreate方法中初始化验证器:
      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_auth)
          auth = Firebase.auth
          auth.setLanguageCode("es")
      
          // 初始化reCAPTCHA验证器,替换为你的站点密钥
          recaptchaVerifier = FirebaseRecaptchaVerifier.Builder("你的reCAPTCHA站点密钥")
              .build(this)
      
          setup()
      }
      
    • 修改注册按钮点击逻辑,先完成reCAPTCHA验证再执行注册:
      signUpBtn.setOnClickListener {
          Log.d("EncuestaMovilidad", "setOnClickListener")
          val email = emailTxt.text.toString()
          val password = passwordTxt.text.toString()
      
          if (email.isEmpty() || password.isEmpty()) {
              Log.d("EncuestaMovilidad", "email and password empty")
              return@setOnClickListener
          }
      
          // 先执行reCAPTCHA验证
          recaptchaVerifier.verifyWithCallbacks(object : FirebaseRecaptchaCallbacks() {
              override fun onSuccess(token: String) {
                  // 验证成功,携带token执行注册
                  val credential = EmailAuthProvider.getCredential(email, password)
                  credential.setRecaptchaToken(token)
      
                  auth.createUserWithCredential(credential)
                      .addOnCompleteListener { task ->
                          if (task.isSuccessful) {
                              Log.d("EncuestaMovilidad", "SUCCESS")
                              val uid = Firebase.auth.currentUser?.uid
                              Log.d("EncuestaMovilidad", "uid: $uid")
                              showHome(task.result.user?.email.toString(), ProviderType.BASIC)
                          } else {
                              val exception = task.exception
                              showErrorAlert("${exception?.message}")
                              Log.e("EncuestaMovilidad", "createUserWithEmail:failure", task.exception)
                          }
                      }
              }
      
              override fun onFailure(e: FirebaseException) {
                  showErrorAlert("reCAPTCHA验证失败:${e.message}")
                  Log.e("EncuestaMovilidad", "reCAPTCHA verification failed", e)
              }
          })
      }
      

    登录按钮逻辑类似,只需将createUserWithCredential替换为signInWithCredential即可。

  3. 可选:使用隐形reCAPTCHA
    若不想显示reCAPTCHA控件,可配置隐形验证,初始化时添加尺寸设置:

    recaptchaVerifier = FirebaseRecaptchaVerifier.Builder("你的reCAPTCHA站点密钥")
        .setSize(FirebaseRecaptchaVerifier.SIZE_INVISIBLE)
        .build(this)
    

注意事项

  • 确保reCAPTCHA站点密钥与Firebase项目绑定正确,否则验证会失败。
  • 若应用已发布到Google Play且启用了App Check,可能无需额外手动处理reCAPTCHA(App Check会自动完成验证)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 00:27:18