【问题标题】:Cannot read data from firebase - Firebase DatabaseError: Permission denied无法从 Firebase 读取数据 - Firebase DatabaseError:权限被拒绝
【发布时间】:2019-04-27 11:30:06
【问题描述】:

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

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

这是 write 方法(效果很好):

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 Console 我还包括登录和注册方法:

登录方式:

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

这里是注册方法:

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

我不知道出了什么问题。帮助表示赞赏。谢谢

【问题讨论】:

  • 请不要在您的问题中包含您的解决方案。问题用于问题,答案用于答案:) 如果您认为您的解决方案为其他答案添加了一些内容,请随时发布。回答自己的问题绝对没有错。
  • @AndréKool 好的 :)

标签: java android firebase firebase-realtime-database firebase-security


【解决方案1】:

你正在尝试从/users这里读取:

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

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

如果你想读取用户自己的数据,读取那个特定的子节点:

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

现在由于用户拥有自己节点的读取权限,所以监听器将被允许。

【讨论】:

  • 这行得通!我进一步更改了读取方法,现在它可以按要求工作了。谢谢。
【解决方案2】:

确保应用名称和客户端 ID 与 Firebase 控制台中的相同。

如果您不确定从项目控制台重新下载 google-services.json 并将其添加到您的项目中。

并在开发和测试期间将您的规则更改为此

{
  "rules": {
    ".read": true,
    ".write": true
  }
}

【讨论】:

    猜你喜欢
    • 2018-03-06
    • 2018-12-12
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多