我是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'"
}
}
}
}
答案 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;
}