首页 > 解决方案 > 无法从 Firebase 读取数据 - Firebase DatabaseError:权限被拒绝

问题描述

我创建了一个简单的应用程序,用户可以在该应用程序上注册登录。身份验证工作正常。我还添加了一个实时数据库。当我尝试从 firebase 读取数据时,我得到“权限被拒绝”,尽管“写入数据”工作正常。我想获取登录用户的数据。这是firebase规则:

 {
  "rules": {
    "users": {
      "$userId": {
        ".write": "$userId === auth.uid",
        ".read": "$userId === auth.uid"
      }
    }
  }
}

这是写方法(这很完美):

public void writeUserInfo(){
        String username = etUserName.getText().toString().trim();
        String age = etAge.getText().toString().trim();
        String sex = etSex.getText().toString().trim();

        if(username.isEmpty()){
            etUserName.setError("user name required");
            etUserName.requestFocus();
            return;
        }
        if(age.isEmpty()){
            etAge.setError("age required");
            etAge.requestFocus();
            return;
        }
        if(sex.isEmpty()){
            etSex.setError("sex required");
            etSex.requestFocus();
            return;
        }

        User user = new User(username,age,sex);
        mDatabase.child("users/"+firebaseUser.getUid()).setValue(user);
    }

这是读取方法:

public void readUserData(){
        mDatabase.child("users").orderByChild(userId).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                if(dataSnapshot.exists()){
                    //array list to staore user data as elements
                    ArrayList<User> userData = new ArrayList<>();
                    for(DataSnapshot snapshot:dataSnapshot.getChildren()){
                        User element = snapshot.getValue(User.class);
                        userData.add(element);
                    }

                    for(User user: userData){
                        etUserName.setText(user.getmUsername());
                        etAge.setText(user.getmAge());
                        etSex.setText(user.getmSex());
                    }
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
    }

这是数据库层次结构: Firebase 控制台 我还包括登录和注册方法:

登录方式:

public void signIn(){
        String userEmail = etEmail.getText().toString().trim();
        String userPassword = etPassword.getText().toString().trim();

        //validation
        //validation
        if(userEmail.isEmpty()){
            etEmail.setError("Email is required");
            //et is focused
            etEmail.requestFocus();
            return;
        }

        if(!Patterns.EMAIL_ADDRESS.matcher(userEmail).matches()){
            etEmail.setError("Invalid email address");
            //focus et
            etEmail.requestFocus();
            return;
        }
        if(userPassword.isEmpty()){
            etPassword.setError("Password is required");
            //et is focused
            etPassword.requestFocus();
            return;
        }
        if(userPassword.length()<6){
            etPassword.setError("Password length should be atleast 6 characters");
            //request focus
            etPassword.requestFocus();
            return;
        }

        //setting progress bar
        progressBar.setVisibility(View.VISIBLE);

        //firebase signin method
        mAuth.signInWithEmailAndPassword(userEmail,userPassword).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {

                //hiding progress bar
                progressBar.setVisibility(View.GONE);

                if(task.isSuccessful()){
                    Intent intent = new Intent(getApplicationContext(),Profile.class);
                    //this flag will clear all the open activities
                    //so that user cant go back to login activyty upon pressing
                    //back button
                    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    startActivity(intent);
                    finish();

                    Toast.makeText(getApplicationContext(),"Logged in successfully",Toast.LENGTH_SHORT).show();
                }else{
                    Toast.makeText(getApplicationContext(),task.getException().getMessage(),Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

这是signUp方法:

public void userRegistration(){
        String userEmail = etSignupEmail.getText().toString().trim();
        String userPassword = etSignupPassword.getText().toString().trim();


        //validation
        if(userEmail.isEmpty()){
            etSignupEmail.setError("Email is required");
            //et is focused
            etSignupEmail.requestFocus();
            return;
        }

        if(!Patterns.EMAIL_ADDRESS.matcher(userEmail).matches()){
            etSignupEmail.setError("Invalid email address");
            //focus et
            etSignupEmail.requestFocus();
            return;
        }
        if(userPassword.isEmpty()){
            etSignupPassword.setError("Password is required");
            //et is focused
            etSignupPassword.requestFocus();
            return;
        }
        if(userPassword.length()<6){
            etSignupPassword.setError("Password length should be atleast 6 characters");
            //request focus
            etSignupPassword.requestFocus();
            return;
        }

        //showing progressbar upon regisration process lifetime
        progressBar.setVisibility(View.VISIBLE);

        //calling firebase register users methods via mAuth instance
        mAuth.createUserWithEmailAndPassword(userEmail,userPassword).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                //changing visibility of progress bar to gone upon registration
                progressBar.setVisibility(View.GONE);

                //checking if the process was successful
                //using this task obj
                if(task.isSuccessful()){
                    Toast.makeText(getApplicationContext(),"user registered successfully", Toast.LENGTH_SHORT).show();
                }else{
                    //this line checks whether the email is already registered or not
                    //using the task obj and FirebasesuthUSerCollisonException
                    if(task.getException() instanceof FirebaseAuthUserCollisionException){
                        Toast.makeText(getApplicationContext(),"email already exists",Toast.LENGTH_SHORT).show();
                    }else{
                        Toast.makeText(getApplicationContext(),task.getException().getMessage(),Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });
    }

我无法弄清楚出了什么问题。帮助表示赞赏。谢谢

标签: javaandroidfirebasefirebase-realtime-databasefirebase-security

解决方案


您正试图从/users这里阅读:

mDatabase.child("users").orderByChild(userId).addValueEventListener(new ValueEventListener() {

但是您的规则只允许用户访问/users/$uid. 由于用户对 没有读取权限/users,因此侦听器被拒绝。

如果要读取用户自己的数据,请读取该特定子节点:

mDatabase.child("users").child(userId).addValueEventListener(new ValueEventListener() {

现在,由于用户对自己的节点具有读取权限,因此将允许侦听器。


推荐阅读