How to validate user with respect to my Realtime Database along with OTP verification?

非 Y 不嫁゛ 提交于 2019-12-08 09:07:23

问题


I have created an Android app in Android Studio and linked it with Firebase Realtime database. I have used Firebase's Authentication by phone and Notification Services to send OTP to the CUG phone no. and then verify it(The code is given below).

public class PhoneLogin extends AppCompatActivity {

private static final String TAG = "PhoneLogin";
private boolean mVerificationInProgress = false;
private String mVerificationId;
private PhoneAuthProvider.ForceResendingToken mResendToken;
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
private FirebaseAuth mAuth;
TextView t1,t2;
ImageView i1;
EditText e1,e2;
Button b1,b2;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_phone_login);

    e1 = (EditText) findViewById(R.id.Phonenoedittext); //Enter Phone no.
    b1 = (Button) findViewById(R.id.PhoneVerify);       //Send OTP button
    t1 = (TextView)findViewById(R.id.textView2Phone);   //Telling user to enter phone no.
    i1 = (ImageView)findViewById(R.id.imageView2Phone); //Phone icon
    e2 = (EditText) findViewById(R.id.OTPeditText);     //Enter OTP
    b2 = (Button)findViewById(R.id.OTPVERIFY);          //Verify OTP button
    t2 = (TextView)findViewById(R.id.textViewVerified); //Telling user to enter otp
    mAuth = FirebaseAuth.getInstance();
    mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
        @Override
        public void onVerificationCompleted(PhoneAuthCredential credential) {
            // Log.d(TAG, "onVerificationCompleted:" + credential);
            mVerificationInProgress = false;
            Toast.makeText(PhoneLogin.this,"Verification Complete",Toast.LENGTH_SHORT).show();
            signInWithPhoneAuthCredential(credential);
        }

        @Override
        public void onVerificationFailed(FirebaseException e) {
            // Log.w(TAG, "onVerificationFailed", e);
            Toast.makeText(PhoneLogin.this,"Verification Failed",Toast.LENGTH_SHORT).show();
            if (e instanceof FirebaseAuthInvalidCredentialsException) {
                // Invalid request
                Toast.makeText(PhoneLogin.this,"InValid Phone Number",Toast.LENGTH_SHORT).show();
                // ...
            } else if (e instanceof FirebaseTooManyRequestsException) {
            }
        }

        @Override
        public void onCodeSent(String verificationId,
                               PhoneAuthProvider.ForceResendingToken token) {
            // Log.d(TAG, "onCodeSent:" + verificationId);
            Toast.makeText(PhoneLogin.this,"Verification code has been sent",Toast.LENGTH_SHORT).show();
            // Save verification ID and resending token so we can use them later
            mVerificationId = verificationId;
            mResendToken = token;
            e1.setVisibility(View.GONE);
            b1.setVisibility(View.GONE);
            t1.setVisibility(View.GONE);
            i1.setVisibility(View.GONE);
            t2.setVisibility(View.VISIBLE);
            e2.setVisibility(View.VISIBLE);
            b2.setVisibility(View.VISIBLE);
            // ...
        }
    };

    b1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            PhoneAuthProvider.getInstance().verifyPhoneNumber(
                    e1.getText().toString(),
                    60,
                    java.util.concurrent.TimeUnit.SECONDS,
                    PhoneLogin.this,
                    mCallbacks);
        }
    });

    b2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, e2.getText().toString());
            // [END verify_with_code]
            signInWithPhoneAuthCredential(credential);
        }
    });


}

private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        // Log.d(TAG, "signInWithCredential:success");
                        startActivity(new Intent(PhoneLogin.this,NavigationDrawer.class));
                        Toast.makeText(PhoneLogin.this,"Verification Done",Toast.LENGTH_SHORT).show();
                        // ...
                    } else {
                        // Log.w(TAG, "signInWithCredential:failure", task.getException());
                        if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                            // The verification code entered was invalid
                            Toast.makeText(PhoneLogin.this,"Invalid Verification",Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            });
}
}

Now I want to add another verification that the entered CUG no. exists in my database and then only the OTP authentication should take place. My database looks like this:

My database

and the code to access this database could be

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference phoneNumberRef = 
rootRef.child("Employees").child(PhoneNumberenteredByUser);
ValueEventListener eventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
    if(dataSnapshot.exists()) {
        //do something
    } else {
        //do something else
    }
}

@Override
public void onCancelled(DatabaseError databaseError) {}
};
phoneNumberRef.addListenerForSingleValueEvent(eventListener);

Also, when I saw about the rules of Firebase Realtime database I noticed that it shouldn't be left public but if I need to keep it private then the user should be authenticated first, so do I need to first authenticate the user by OTP and then check if the user CUG no. exists in my database?

Edited code which is authenticating any no. even if it's not in my database:

public class PhoneLogin extends AppCompatActivity {
private static final String TAG = "PhoneLogin";
private boolean mVerificationInProgress = false;
private String mVerificationId;
private PhoneAuthProvider.ForceResendingToken mResendToken;
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
private FirebaseAuth mAuth;
TextView t1,t2;
ImageView i1;
EditText e1,e2;
Button b1,b2;

//DBA1
private DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
private DatabaseReference phoneNumberRef;
String mobno;
//DBA1 End

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_phone_login);

    e1 = (EditText) findViewById(R.id.Phonenoedittext);
    b1 = (Button) findViewById(R.id.PhoneVerify);
    t1 = (TextView) findViewById(R.id.textView2Phone);
    i1 = (ImageView) findViewById(R.id.imageView2Phone);
    e2 = (EditText) findViewById(R.id.OTPeditText);
    b2 = (Button) findViewById(R.id.OTPVERIFY);
    t2 = (TextView) findViewById(R.id.textViewVerified);

    mobno=e1.getText().toString();

    //DBA2
    phoneNumberRef = rootRef.child("Employees").child(mobno);
    ValueEventListener eventListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.exists()) {
                mAuth = FirebaseAuth.getInstance();
                mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {


                    @Override
                    public void onVerificationCompleted(PhoneAuthCredential credential) {
                        // Log.d(TAG, "onVerificationCompleted:" + credential);
                        mVerificationInProgress = false;
                        Toast.makeText(PhoneLogin.this,"Verification Complete",Toast.LENGTH_SHORT).show();
                        signInWithPhoneAuthCredential(credential);
                    }

                    @Override
                    public void onVerificationFailed(FirebaseException e) {
                        // Log.w(TAG, "onVerificationFailed", e);
                        Toast.makeText(PhoneLogin.this,"Verification Failed",Toast.LENGTH_SHORT).show();
                        if (e instanceof FirebaseAuthInvalidCredentialsException) {
                            // Invalid request
                            Toast.makeText(PhoneLogin.this,"InValid Phone Number",Toast.LENGTH_SHORT).show();
                            // ...
                        } else if (e instanceof FirebaseTooManyRequestsException) {
                        }

                    }

                    @Override
                    public void onCodeSent(String verificationId,
                                           PhoneAuthProvider.ForceResendingToken token) {
                        // Log.d(TAG, "onCodeSent:" + verificationId);
                        Toast.makeText(PhoneLogin.this,"Verification code has been sent",Toast.LENGTH_SHORT).show();
                        // Save verification ID and resending token so we can use them later
                        mVerificationId = verificationId;
                        mResendToken = token;
                        e1.setVisibility(View.GONE);
                        b1.setVisibility(View.GONE);
                        t1.setVisibility(View.GONE);
                        i1.setVisibility(View.GONE);
                        t2.setVisibility(View.VISIBLE);
                        e2.setVisibility(View.VISIBLE);
                        b2.setVisibility(View.VISIBLE);
                        // ...
                    }
                };

                b1.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        PhoneAuthProvider.getInstance().verifyPhoneNumber(
                                e1.getText().toString(),
                                60,
                                java.util.concurrent.TimeUnit.SECONDS,
                                PhoneLogin.this,
                                mCallbacks);
                    }
                });

                b2.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, e2.getText().toString());
                        // [END verify_with_code]
                        signInWithPhoneAuthCredential(credential);
                    }
                });



            } else {
                Toast.makeText(getApplicationContext(),"Incorrect CUG",Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    };
    phoneNumberRef.addListenerForSingleValueEvent(eventListener);
    //DBA2 End


}
private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        startActivity(new Intent(PhoneLogin.this,NavigationDrawer.class));
                        Toast.makeText(PhoneLogin.this,"Verification Done",Toast.LENGTH_SHORT).show();
                        // Log.d(TAG, "signInWithCredential:success");
                        //startActivity(new Intent(PhoneLogin.this,NavigationDrawer.class));
                        Toast.makeText(PhoneLogin.this,"Verification Done",Toast.LENGTH_SHORT).show();
                        // ...
                    } else {
                        // Log.w(TAG, "signInWithCredential:failure", task.getException());
                        if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                            // The verification code entered was invalid
                            Toast.makeText(PhoneLogin.this,"Invalid Verification",Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            });
}
}

回答1:


It's easy,

edit your

b2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, e2.getText().toString());
                    // [END verify_with_code]
                    signInWithPhoneAuthCredential(credential);
                }
            });

with:

b2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
//Write your database reference and check in the database for entered mobno.
rootRef.addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    if(dataSnapshot.child(mobno).exists()){
                        PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, e2.getText().toString());
                    // [END verify_with_code]
                    signInWithPhoneAuthCredential(credential);
                    }
                    else{
                        Toast.makeText(PhoneLogin.this,"No such CUG No. found",Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }
            });



回答2:


I hope this helps! I had such a scenario but had a workaroud to it. First when adding data to "Employees", you can get the userId add an extra node with the userID. Lets try this

DatabaseReference rootRef=FirebaseDatabase.getInstance().getReference("Employees");
FirebaseAuth firebaseAuth;
FirebaseUser user=firebaseAuth.getInstance().getCurrentUser();
rootRef.child(user.getUid()).setValue(youModelClassObject);//rootRef is your database reference

This means on every user added to "Employees" there will be a node with their userID. Now when trying to access the database and check whether the userId which has been authenticated can be found under the employees. I would have done the following..

rootRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for(DataSnapshot ds : dataSnapshot.getChildren()) {

                Object obj=ds.getKey();                     //

                Firebase user = firebaseAuth.getInstance().getCurrentUser();
                String myId=user.getUid();

                //Specify your model class here
                ModelClass modelObject=new ModelClass();

              if(Objects.equals(myId, obj.toString())) 
                    {
                         //assuming you've set getters and setters in your model class
                         modelObject.setPhone(ds.getValue(ModelClass.class).getPhone());

                         String myDatabasePhone=modelObject.getPhone();
                         if (myDatabasePhone!=null)
                           {
                             //Now call the second OTP verification method and pass 'myDatabasePhone'
                           }                                 

                    }else {
                  //User not found
                  //direct them to a signup Activy
                    }

            }

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });`enter code here`



回答3:


No, by the time you are trying to authenticate the user, you need to check if the user exists. So you need to check first and then authenticate. Your code looks perfectly fine.

Regarding the rules, it's true, it shouldn't be left public. So allow only the authenticated users to make changes in your database.



来源:https://stackoverflow.com/questions/49314285/how-to-validate-user-with-respect-to-my-realtime-database-along-with-otp-verific

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!