身份验证和实时数据库同时进行?

Posted

技术标签:

【中文标题】身份验证和实时数据库同时进行?【英文标题】:Authentication and Realtime Database at the same time? 【发布时间】:2021-09-27 14:50:21 【问题描述】:

我目前正在开发一个移动应用程序,作为我课程的最后一个项目。我使用 Firebase 作为应用程序的数据库。我在我们的应用中使用身份验证作为登录活动的工具。

现在,我在我的应用程序中使用实时数据库作为另一个工具来保存和检索数据。不幸的是,数据库没有保存我在注册活动中输入的数据,但我可以登录应用程序。我的问题是身份验证和实时数据库有可能在我的应用程序中同时工作吗?

这是我的代码。

登录活动:

public class Bio_LogIn extends AppCompatActivity 

    @Override
    protected void onCreate(Bundle savedInstanceState) 

        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getSupportActionBar().hide(); // hides the action bar.

        setContentView(R.layout.activity_bio_log_in);

        //Firebase class, texbox/es and button/s declaration
        FirebaseAuth FbaseAuth_LI = FirebaseAuth.getInstance();
        TextInputEditText txtbx_Username = findViewById(R.id.txtbx_Username);
        TextInputEditText txtbx_Password = findViewById(R.id.txtbx_SU_ConfirmPass);
        Button btn_Log_In = findViewById(R.id.btn_Log_In);
        Button btn_Forget_Pass = findViewById(R.id.btn_Forget_Pass);
        Button btn_Sign_Up = findViewById(R.id.btn_Sign_Up);
        AlertDialog.Builder alert_forget_pass = new AlertDialog.Builder(this);
        LayoutInflater inflater_alert = this.getLayoutInflater();

        btn_Log_In.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                // data extraction and validation
                if(txtbx_Username.getText().toString().isEmpty()) // gives error message when no username or email address input
                    txtbx_Username.setError("Email Address is missing."); // error message
                    return;
                
                if(txtbx_Password.getText().toString().isEmpty()) // gives error message when no password input
                    txtbx_Password.setError("Password is missing."); // error message
                    return;
                
                // successful account login
                FbaseAuth_LI.signInWithEmailAndPassword(txtbx_Username.getText().toString(),txtbx_Password.getText().toString()).addOnSuccessListener(new OnSuccessListener<AuthResult>() 
                    @Override
                    public void onSuccess(AuthResult authResult) 
                        startActivity(new Intent(getApplicationContext(), MM_Play.class));
                        finish();
                    
                ).addOnFailureListener(new OnFailureListener()  //
                    @Override
                    public void onFailure(@NonNull Exception e) 
                        Toast.makeText(Bio_LogIn.this, e.getMessage(), Toast.LENGTH_LONG).show();
                    
                );
            
        );

        btn_Forget_Pass.setOnClickListener(new View.OnClickListener() 
            // When "Forget Password" is clicked, an alert dialog will appear.
            @Override
            public void onClick(View v) 

                View view = inflater_alert.inflate(R.layout.alert_forget_pass, null);
                alert_forget_pass.setTitle("Forget Password ?")
                        .setMessage("Enter your Email Address to get a Password Reset link.")
                        .setPositiveButton("Reset", new DialogInterface.OnClickListener() 
                            @Override
                            public void onClick(DialogInterface dialog, int which) 

                                TextInputEditText txtbx_FP_Email = view.findViewById(R.id.txtbx_FP_Email);
                                if(txtbx_FP_Email.getText().toString().isEmpty()) 
                                    txtbx_FP_Email.setError("Required Field");
                                    return;
                                
                                FbaseAuth_LI.sendPasswordResetEmail(txtbx_FP_Email.getText().toString()).addOnSuccessListener(new OnSuccessListener<Void>() 
                                    @Override
                                    public void onSuccess(Void aVoid) 
                                        Toast.makeText(Bio_LogIn.this, "Password Reset Link Sent", Toast.LENGTH_LONG).show();
                                    
                                ).addOnFailureListener(new OnFailureListener() 
                                    @Override
                                    public void onFailure(@NonNull  Exception e) 
                                        Toast.makeText(Bio_LogIn.this, e.getMessage(), Toast.LENGTH_LONG).show();
                                    
                                );
                            
                        ).setNegativeButton("Cancel", null)
                        .setView(view)
                        .create().show();
            
        );

        btn_Sign_Up.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                startActivity(new Intent(Bio_LogIn.this, Bio_SignUp.class));;
            
        );
    

    // when the user already logged in in the app, they will go directly to the game.
    @Override
    protected void onStart() 
        super.onStart();
        if(FirebaseAuth.getInstance().getCurrentUser() != null)
            startActivity(new Intent(getApplicationContext(), MM_Play.class));
            finish();
        
    

注册活动:

public class Bio_SignUp extends AppCompatActivity 
    EditText txtbx_SU_FullName, txtbx_SU_Email, txtbx_SU_Pass, txtbx_SU_ConfirmPass; // edit text declarations.
    Button btn_Register; // button/s declaration/s.
    ImageButton btn_SU_Back;
    FirebaseAuth FbaseAuth_SU; //for authentication
    FirebaseDatabase rootNode; // for realtime database
    DatabaseReference reference;


    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getSupportActionBar().hide(); // hides the action bar.

        setContentView(R.layout.activity_bio_sign_up);

        txtbx_SU_FullName = findViewById(R.id.txtbx_SU_FullName);
        txtbx_SU_Email = findViewById(R.id.txtbx_SU_Email);
        txtbx_SU_Pass = findViewById(R.id.txtbx_SU_Pass);
        txtbx_SU_ConfirmPass = findViewById(R.id.txtbx_SU_ConfirmPass);
        btn_Register = findViewById(R.id.btn_Register);
        btn_SU_Back = findViewById(R.id.btn_SU_Back);

        FbaseAuth_SU = FirebaseAuth.getInstance();
        rootNode = FirebaseDatabase.getInstance();
        reference = rootNode.getReference("users");

        btn_Register.setOnClickListener(new View.OnClickListener() 

            @Override
            public void onClick(View v) 


                String fullname = txtbx_SU_FullName.getText().toString();
                String email = txtbx_SU_Email.getText().toString();
                String password = txtbx_SU_Pass.getText().toString();
                String ConPassword = txtbx_SU_ConfirmPass.getText().toString();
                UserHelper UHelper = new UserHelper(fullname, email, password);

                if(fullname.isEmpty() && email.isEmpty() && password.isEmpty()) // condition if full name field is empty,
                    txtbx_SU_FullName.setError("This field cannot be empty."); // this error message will be shown.
                    return;
                

                if (!ConPassword.equals(password)) // condition if the confirm password is not equals to password,
                    txtbx_SU_ConfirmPass.setError("Password does not match."); // this error message will be shown.
                    return;
                

                reference.addValueEventListener(new ValueEventListener() 
                    @Override
                    public void onDataChange(@NonNull DataSnapshot snapshot) 
                        reference.child(fullname).setValue(UHelper);
                    

                    @Override
                    public void onCancelled(@NonNull DatabaseError error) 
                        Toast.makeText(getApplicationContext(),error.getMessage(), Toast.LENGTH_LONG).show();
                    
                );

                Toast.makeText(Bio_SignUp.this, "Data Validated", Toast.LENGTH_LONG).show(); // notification that data is validated.

                FbaseAuth_SU.createUserWithEmailAndPassword(email, password).addOnSuccessListener(new OnSuccessListener<AuthResult>() 
                    @Override
                    public void onSuccess(AuthResult authResult)  // send the user to the log - in screen.
                        startActivity(new Intent(getApplicationContext(), Bio_LogIn.class));
                        finish();
                    
                ).addOnFailureListener(new OnFailureListener() 
                    @Override
                    public void onFailure(@NonNull Exception e)  // an error when email and pass is wrong or invalid.
                        Toast.makeText(Bio_SignUp.this, e.getMessage(), Toast.LENGTH_LONG).show();
                    
                );
            
        );

        btn_SU_Back.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                finish();
            
        );
    

【问题讨论】:

【参考方案1】:

所以,首先,这一行

Toast.makeText(Bio_SignUp.this, "Data Validated", Toast.LENGTH_LONG).show();

即使将值设置为realtime database 失败以及createUserWithEmailAndPassword 失败时也会执行,因为它位于onSuccess 块之外,因此目前Toast 消息Data Validated 没有说明任何内容。

其次,您不需要在此处使用ValueEventListener 将值设置为firebase。它用于reading 值,在此代码中从未使用过DataSnapshot。所以可以直接拨打.setValue(UHelper)

你想要做的是,在createUserWithEmailAndPasswordBio_SignUp Activity 的onSuccess 方法中,调用这个setValue(uHelper)

            FbaseAuth_SU.createUserWithEmailAndPassword(email, password).addOnSuccessListener(new OnSuccessListener<AuthResult>() 
                @Override
                public void onSuccess(AuthResult authResult)  // send the user to the log - in screen.

                    reference.setValue(uHelper).addOnSuccessListener(new OnSuccessListener

                   @Override
                   public void onSuccess() 

                   Toast.makeText(Bio_SignUp.this, "Data Validated", Toast.LENGTH_LONG).show();

                    startActivity(new Intent(getApplicationContext(), Bio_LogIn.class));
                    finish();
                
              
            ).addOnFailureListener(new OnFailureListener() 
                @Override
                public void onFailure(@NonNull Exception e)  // an error when email and pass is wrong or invalid.
                    Toast.makeText(Bio_SignUp.this, e.getMessage(), Toast.LENGTH_LONG).show();
                
            );

【讨论】:

【参考方案2】:

身份验证和实时数据库是否可以在我的应用中同时工作?

是的,可以在同一个应用中使用 Firebase 身份验证和实时数据库。例如,您可以查看面向 android 开发人员的 Firebase 代码实验室here。

这意味着问题可能出在您的代码中,您需要对其进行调试以找出问题所在。我会在下面指出一些地方,但可能还有更多问题。


这看起来很不寻常:

reference.addValueEventListener(new ValueEventListener() 
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) 
        reference.child(fullname).setValue(UHelper);
    

    @Override
    public void onCancelled(@NonNull DatabaseError error) 
        Toast.makeText(getApplicationContext(),error.getMessage(), Toast.LENGTH_LONG).show();
    
);

由于您没有对onDataChange 中的数据进行任何操作,因此无需先阅读它。我建议用这一行替换上面的代码:

reference.child(fullname).setValue(UHelper);

我通常还会向add a completion listener 推荐此电话,以便您在其中出现问题时进行记录。


Firebase 客户端需要知道您的数据库 URL 才能在服务器上找到您的数据库。

此代码从您从 Firebase 控制台下载的 google-services.json 文件中读取该 URL:

rootNode = FirebaseDatabase.getInstance();

最近我们看到一些开发人员在在控制台中创建数据库之前下载 JSON 文件时访问数据库时遇到问题。

如果您遇到同样的问题,可以通过在代码中直接指定数据库 URL 来解决:

rootNode = FirebaseDatabase.getInstance("database URL here");

【讨论】:

以上是关于身份验证和实时数据库同时进行?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Firebase 身份验证服务并在我们自己的数据库中拥有用户?

如何在 Spring 安全性中同时使用数据库和 LDAP 身份验证?

当我们有一个身份验证系统时,如何为某些链接添加基本身份验证

Laravel Api 和 Web 身份验证同时进行

我们如何在同一spring应用程序中同时添加JWT和基本身份验证?

如何在 ASP.NET Core 3 上同时使用 Azure AD 身份验证和身份?