验证后读取数据时,Firebase权限被拒绝

时间:2015-11-09 10:16:11

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

我是Firebase的新手。我使用电子邮件和密码对用户进行了身份验证 -

final Firebase ref = new Firebase("https://app.firebaseio.com");
ref.authWithPassword("app@firebaseio.com", "password", new Firebase.AuthResultHandler() {

    @Override
    public void onAuthenticated(AuthData authData) {
        System.out.println("User ID: " + authData.getUid());
        getData(ref);
    }

    @Override
    public void onAuthenticationError(FirebaseError firebaseError) {
    }
});

但在我阅读数据后进行身份验证后,我收到Permission Denied

private void getData(Query ref) {
    ref.addValueEventListener(new ValueEventListener() {

        @Override
        public void onDataChange(DataSnapshot snapshot) {
            System.out.println(snapshot.getValue());
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {
            System.out.println("The read failed: " + firebaseError.getMessage());
        }
    });
}

这些是Firebase规则。

{
    "rules": {
        "users": {
            "$uid": {
                ".read": "auth !== null && auth.provider === 'password'"
            }
        }
    }
}

3 个答案:

答案 0 :(得分:7)

Firebase的权限模型仅允许用户访问您明确授予访问权限的数据。由于在您的安全规则中,您只能访问/users/$uid,因此用户无法从根/读取。 Firebase文档涵盖了"rules cascade"下的内容。

您似乎希望使用安全规则来过滤数据,这是Firebase的安全模型无法实现的。请参阅Firebase文档中的"rules are not filters"部分以及之前的问题和答案:

最简单的解决方案是允许读取users节点:

{
    "rules": {
        "users": {
            ".read": "auth !== null && auth.provider === 'password'"
        }
    }
}

然后在该级别进行查询:

getData(ref.child("users"));

答案 1 :(得分:2)

我使用稍微不同的方法从我的数据库中读取此异常,但这就是我解决问题的方法。

首先,我的数据库规则看起来很喜欢这个:

 mAuthListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            user = firebaseAuth.getCurrentUser();
            if (user != null) {
                // User is signed in
                Log.e(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
            } else {
                // User is signed out
                Log.e(TAG, "onAuthStateChanged:signed_out");
            }
            // ...
        }
    };
    ...
    Student student = new Student();
    student.setPhoneNumber("+23480547455343");
    student.setCountryOfOrigin("Nigeria");
    mDatabaseReference.child("student").child(user.getUid()).setValue(student).
                addOnCompleteListener(DetailsCaptureActivity.this, 
                                   new OnCompleteListener<Void>() {
     ...
     });

早些时候,为了写入学生数据库,我在我的活动中使用了这段代码:

 //Set up an AuthStateListener that responds to changes in the user's sign-in state:
    mAuthListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            user = firebaseAuth.getCurrentUser();
            if (user != null) {

                   databaseReference = firebaseDatabase.getReference().child("student").child(user.getUid());
                   databaseReference.addValueEventListener(new ValueEventListener() {
                      @Override
                      public void onDataChange(DataSnapshot dataSnapshot) {
                          Student student = dataSnapshot.getValue(Student.class);
                          phoneNumberTextView.setText(student.getPhoneNumber());
                      }

                      @Override
                      public void onCancelled(DatabaseError databaseError) {

                          Log.e(TAG, databaseError.getMessage());
                      }
                  });

            } else {
                Log.e(TAG, "onAuthStateChanged:signed_out");
            }
        }
    };

注意子名称(学生)如何与firebase数据规则中的子名称匹配?

现在要阅读这个用户的数据,我这样做了:

databaseReference = firebaseDatabase.getReference().child(user.getUid());

如果我只做了,我获得了许可被拒绝的例外:

\\remotecomputerIP\c$

答案 2 :(得分:1)

问题是Firebase有一个错误,在验证后,您必须等到用户出现在FirebaseAuth中,然后才能使用它。

我所做的是等待它出现,如

Observable.fromCallable(() -> signInImpl())
        .map(this::toFirebaseUser)
        .map(this::waitForUserToAppearInAuthenticator)
        .flatMap(this::doSomethingInDatabase);

其中

@NonNull
private FirebaseUser waitForUserToAppearInAuthenticator(@NonNull final FirebaseUser user) {
    final CountDownLatch cdl = new CountDownLatch(1);
    final FirebaseAuth.AuthStateListener l = firebaseAuth -> {
        final FirebaseUser cu = firebaseAuth.getCurrentUser();
        if (cu != null && user.getUid().equals(cu.getUid())) {
            cdl.countDown();
        }
    };
    mFirebaseAuth.addAuthStateListener(l);
    try {
        cdl.await(20, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    } finally {
        mFirebaseAuth.removeAuthStateListener(l);
    }

    return user;
}