简体   繁体   English

Firebase 注册前验证用户

[英]Firebase verify user before sign up

I want to verify a user before I can allow signup, however, the verification always fails on the first call even when data is correct我想在允许注册之前验证用户,但是,即使数据正确,验证也总是在第一次调用时失败

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
    } 

isAprroved is always false since verifyApprovedUser function calls an asynchronous function, so createUserWithEmailAndPassword will be called before onDataChange function. isAprroved始终为false ,因为verifyApprovedUser function 调用异步 function,因此createUserWithEmailAndPassword将在onDataChange function 之前调用。

To fix this, you have to change verifyApprovedUser to return Task<Boolean> with using TaskCompletionSource and chaining by using continueWithTask in signUp function, something like this.要解决此问题,您必须更改verifyApprovedUser以使用TaskCompletionSource返回Task<Boolean>并通过在signUp function 中使用continueWithTask进行链接,如下所示。 (I didn't test code though) (虽然我没有测试代码)

Kotlin Version: Kotlin 版本:

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 Version: 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();
}

However, a recommended approach would be RxJava and Kotlin's Coroutine .但是,推荐的方法是RxJava和 Kotlin 的Coroutine

Plus, you would better to learn what Reactive Programming is.另外,您最好了解什么是Reactive Programming

I dont know how efficient this is, but this is how i managed to implement我不知道这有多有效,但这就是我设法实施的方式

 val approvedUsersList : MutableList<String> = ArrayList()

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

    private fun verifyApprovedUsers() {
        dbRef.addListenerForSingleValueEvent(object : ValueEventListener {
            override fun onDataChange(snapshot: DataSnapshot) {
                approvedUsersList.clear()
                for (data: DataSnapshot in snapshot.children) {
                    approvedUsersList.add(data.value.toString())
                }

        }

This is how my Login Activity Verifies if I already logged in before.这就是我的登录活动验证我之前是否已经登录的方式。

private fun verifyIfUserIsLoggedIn() { // Checks if user has already logged in
        val uid = FirebaseAuth.getInstance().uid

        // This checks if there is a present UID in your Activity
        // If UID == null, intent closes the CurrentActivity and throws you back in RegisterActivity
        if (uid == null) {
            val intent = Intent(this, RegisterActivity::class.java)
            intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK) // Clears previous activity when inflating the new one
            startActivity(intent)
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM