首页 > 解决方案 > Firebase 在注册前验证用户

问题描述

我想在允许注册之前验证用户,但是,即使数据正确,验证也总是在第一次调用时失败

private var isAprroved : Boolean = false

fun signUp(email: String, password: String, idNumber: String): Task<AuthResult>? {
        verifyApprovedUser(idNumber)
        return if (isAprroved) {
            firebaseAuth.createUserWithEmailAndPassword(email, password)
        } else {
            null
        }
    }

    private fun verifyApprovedUser(idNumber: String) {
        dbRef.addListenerForSingleValueEvent(object : ValueEventListener {
            override fun onDataChange(snapshot: DataSnapshot) {
                if (snapshot.child(idNumber).exists()) {
                   updateUserVerified()
                }
            }

            override fun onCancelled(error: DatabaseError) {
                TODO("Not yet implemented")
            }

        })

    }

    fun updateUserVerified() {
        isAprroved = true
    } 

标签: androidfirebasekotlinfirebase-realtime-database

解决方案


isAprroved总是false因为verifyApprovedUser函数调用异步函数,所以createUserWithEmailAndPassword会在onDataChange函数之前调用。

要解决此问题,您必须更改为使用TaskCompletionSourceverifyApprovedUser返回并通过使用in函数进行链接,就像这样。(虽然我没有测试代码)Task<Boolean>continueWithTasksignUp

科特林版本:

private fun signUp(email: String, password: String, idNumber: String): Task<AuthResult?> {
    return verifyApprovedUser(idNumber).continueWithTask { task ->
        if (!task.isSuccessful) {
            return@continueWithTask Tasks.forException<AuthResult?>(task.exception!!)
        }
        val verified: Boolean = task.result
        if (verified) {
            return@continueWithTask FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password)
        } else {
            return@continueWithTask Tasks.forResult<AuthResult?>(null)
        }
    }
}

private fun verifyApprovedUser(idNumber: String): Task<Boolean> {
    val tcs: TaskCompletionSource<Boolean> = TaskCompletionSource()
    FirebaseDatabase.getInstance().reference.addListenerForSingleValueEvent(object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {
            val verified = dataSnapshot.child(idNumber).exists()
            tcs.setResult(verified)
        }

        override fun onCancelled(databaseError: DatabaseError) {
            tcs.setException(databaseError.toException())
        }
    })
    return tcs.task
}  

Java版本:

private Task<AuthResult> signUp(String email, String password, String idNumber) {
    return verifyApprovedUser(idNumber).continueWithTask(task -> {
        if (!task.isSuccessful()) {
            return Tasks.forException(task.getException());
        }
        boolean verified = task.getResult();
        if (verified) {
            return FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password);
        } else {
            return Tasks.forResult(null);
        }
    });
}

private Task<Boolean> verifyApprovedUser(String idNumber) {
    TaskCompletionSource<Boolean> tcs = new TaskCompletionSource<>();
    FirebaseDatabase.getInstance().getReference().addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            boolean verified = dataSnapshot.child(idNumber).exists();
            tcs.setResult(verified);
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            tcs.setException(databaseError.toException());
        }
    });
    return tcs.getTask();
}

但是,推荐的方法是RxJava和 Kotlin 的Coroutine.

另外,您最好了解它是什么Reactive Programming


推荐阅读