android firebase firebase-security firebase-realtime-database

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



firebase-security firebase-realtime-database (3)

Soy nuevo en Firebase. Autentiqué al usuario mediante correo electrónico y contraseña.

final Firebase ref = new Firebase("https://app.firebaseio.com"); ref.authWithPassword("[email protected]", "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, recibo el 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 permisos de Firebase solo permite al usuario acceder a los datos a los que usted otorga acceso explícitamente. Dado que en sus reglas de seguridad, solo le da acceso a /users/$uid , el usuario no puede leer desde la raíz / . La documentación de Firebase cubre esto en "cascada de reglas" .

Parece que quiere 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 estas preguntas y respuestas anteriores:

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


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

Lo que hice fue esperar a que apareciera, 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; }


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, usé 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<Void>() { ... });

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

Obtuve la excepción de permiso denegado si solo hice:

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