Permiso de Firebase denegado al leer datos después de la autenticación

Soy nuevo en Firebase. Autenticé al usuario usando el correo electrónico y la contraseña –

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

Pero después de la autenticación cuando estoy leyendo los datos, 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()); } }); } 

Estas son las reglas de Firebase.

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

El modelo de permiso de Firebase solo permite al usuario acceder a los datos a los que explícitamente le da acceso. Dado que en sus reglas de seguridad, solo da acceso a /users/$uid , el usuario no puede leer desde root / . La documentación de Firebase cubre esto en “cascada de reglas” .

Parece que desea usar reglas de seguridad para filtrar datos, lo cual no es posible con el modelo de seguridad de Firebase. Consulte la sección “las reglas no son filtros” en la documentación de Firebase, así como las preguntas y respuestas anteriores:

  • permiso de seguridad de firebase no funciona
  • reglas de firebase no funcionan
  • Cómo usar las reglas de Firebase para solo dar permiso a ciertos nodos de hoja

La solución más simple es permitir la lectura del nodo de users :

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

Y luego consulta en ese nivel:

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

Obtuve esta excepción usando un enfoque ligeramente diferente para leer desde mi base de datos, pero así es como resolví el problema.

En primer lugar, las reglas de mi base de datos se veían así:

 { "rules": { "student": { "$uid": { ".write": "auth != null && auth.uid == $uid", ".read": "auth != null && auth.uid == $uid" } } } } 

Anteriormente, para escribir en la base de datos de estudiantes, utilicé este código en mi Actividad:

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

¿Observe cómo el nombre del niño (estudiante) coincide con el nombre del niño en las reglas de datos de firebase?

Ahora para leer los datos de este usuario, hice esto:

  //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"); } } }; 

Recibí la excepción de permiso denegado si solo lo hice:

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

El problema es que Firebase tiene un error, que después de la autenticación, tienes que esperar hasta que el usuario aparezca en FirebaseAuth , y luego puedes usarlo.

Lo que hice es esperar que aparezca, como

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

Dónde

 @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; }