在Android版Firebase中无需发送短信即可验证电话号码

时间:2020-04-05 05:27:03

标签: android kotlin firebase-authentication one-time-password

我想使用Firebase电话号码身份验证。我的代码是这样的:

LoginActivity.kt

import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.tasks.Task
import com.google.firebase.FirebaseException
import com.google.firebase.auth.AuthResult
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.PhoneAuthCredential
import com.google.firebase.auth.PhoneAuthProvider
import kotlinx.android.synthetic.main.login_activity.*
import java.util.concurrent.TimeUnit


class LoginActivity : AppCompatActivity() {
    lateinit var mCallbacks: PhoneAuthProvider.OnVerificationStateChangedCallbacks
    lateinit var mAuth: FirebaseAuth
    var verificationId = ""
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.login_activity)
        mAuth = FirebaseAuth.getInstance()
        veriBtn.setOnClickListener {
            if (phnNoTxt.text.toString()!=""){
            progress.visibility = View.VISIBLE
            verify ()}
                else toast("Enter verification number")
        }
        authBtn.setOnClickListener {
            if ((verifiTxt.text.toString()!="")&&(phnNoTxt.text.toString()!="")){
            progress.visibility = View.VISIBLE
            authenticate()}
            else toast("Enter phone number and its verification number")
        }
    }
    private fun verificationCallbacks () {
        mCallbacks = object: PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            override fun onVerificationCompleted(credential: PhoneAuthCredential) {
                progress.visibility = View.INVISIBLE
                signIn(credential)
                Log.d("abc","1")
            }
            override fun onVerificationFailed(p0: FirebaseException) {
                progress.visibility=View.GONE
                Log.d("abc","2")}
            override fun onCodeSent(verfication: String, p1: PhoneAuthProvider.ForceResendingToken) {
                super.onCodeSent(verfication, p1)
                verificationId = verfication
                progress.visibility = View.INVISIBLE
                Log.d("abc","3")
            }
        }
    }
    private fun verify () {
        verificationCallbacks()
        val phnNo ="+"+ phnNoTxt.text.toString()

        PhoneAuthProvider.getInstance().verifyPhoneNumber(
            phnNo,
            60,
            TimeUnit.SECONDS,
            this,
            mCallbacks
        )
    }
    private fun signIn (credential: PhoneAuthCredential) {
        mAuth.signInWithCredential(credential)
            .addOnCompleteListener {
                    task: Task<AuthResult> ->
                if (task.isSuccessful) {
                    toast("Sign in Successfully :)")
                }
            }
    }
    private fun authenticate () {

        val verifiNo = verifiTxt.text.toString()

        val credential: PhoneAuthCredential = PhoneAuthProvider.getCredential(verificationId, verifiNo)

        signIn(credential)

    }
    private fun toast (msg: String) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
    }

}

login_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:layout_gravity="center"
    xmlns:android="http://schemas.android.com/apk/res/android">
            <EditText
                android:id="@+id/phnNoTxt"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:hint="Phone Number"
                android:inputType="number"
                android:textAlignment="center"
                android:textSize="24sp"
                android:gravity="center_horizontal" />

            <EditText
                android:id="@+id/verifiTxt"
                android:text=""
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentStart="true"
                android:textAlignment="center"
                android:inputType="number"
                android:layout_below="@+id/phnNoTxt"
                android:hint="Verification Code"
                android:gravity="center_horizontal"
                android:layout_alignParentLeft="true" />
            <ProgressBar
                android:id="@+id/progress"
                style="?android:attr/progressBarStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:visibility="gone" />

            <Button
                android:id="@+id/veriBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/verifiTxt"
                android:layout_centerHorizontal="true"
                android:layout_gravity="center"
                android:text="Verify" />

            <Button
                android:id="@+id/authBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/veriBtn"
                android:layout_centerHorizontal="true"
                android:layout_gravity="center"
                android:text="Authenticate" />
        </LinearLayout>
</ScrollView>

当我第一次输入电话号码时,Firebase会向我发送短信,实际上是在verificationCallbacks ()中,第三个会运行(onCodeSent)。之后,当我再次在verificationCallbacks ()中输入电话号码时,第一个将运行(onVerificationCompleted)。这是合理的。但是对我来说很奇怪,尽管我希望Firebase可以向我发送短信并(onCodeSent运行,但是再次运行(onVerificationCompleted之后,我还是从Firebase中删除了手机的SMS验证码并从Firebase中删除了我的电话号码。 )跑了。当我在另一部电话中测试时,它可以按我的意愿工作。每次我输入电话号码(在另一个电话中,不是我的SIM卡所在的电话)时,Firebase都会向我发送带有验证码的SMS,如果验证码正确,它将验证我的电话号码。我希望Firebase每次输入电话号码时都向我发送SMS,无论是在SIM卡所在的电话中还是在其他电话中尝试。可能吗?我应该如何更改代码?

1 个答案:

答案 0 :(得分:1)

没有短信似乎无法做到这一点。即使在Firebase文档中,也提到它将通过发送代码通过SMS完成。 以及如何在不使用SMS的情况下验证代码?电话号码不是您的android设备的属性。它在您的操作员的某个地方。 即使您设法以字符串形式获取电话号码并创建自己的方式来验证电话号码,该电话号码也不安全,并且会被反向工程设计所误用。

文档中提到了这一点。

onCodeAutoRetrievalTimeOut(String VerificationId)可选。这个 在指定的超时持续时间后调用该方法 verifyPhoneNumber已通过,且没有onVerificationCompleted 首先触发。在没有SIM卡的设备上,此方法称为 立即进行,因为无法进行SMS自动检索。

现在回到主题,这是可能的,但是在测试期间。 您可以将号码列入白名单,并且不会通过短信发送OTP或代码。 但是,有一些条件。 https://firebase.google.com/docs/auth/android/phone-auth#test-with-whitelisted-phone-numbers

其次,您似乎遇到了删除电话号码但Firebase仍运行onVerificationCmoplete的问题。尝试从“身份验证”选项卡中删除用户并刷新它。而且,如果您的代码跟踪该电话号码或与该号码有关的用户数据,请确保也将其清除。