Разрешение Firebase при чтении данных после аутентификации

Я новичок в Firebase. Я аутентифицировал пользователя с помощью электронной почты и пароля –

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

Но после проверки подлинности, когда я читаю данные, я получаю 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'" } } } } 

Модель разрешения Firebase позволяет пользователю получить доступ к данным, к которым вы явно предоставляете доступ. Поскольку в ваших правилах безопасности вы предоставляете только доступ к /users/$uid , пользователь не может читать из root / . Документация Firebase охватывает это в разделе «каскад правил» .

Кажется, вы хотите использовать правила безопасности для фильтрации данных, что невозможно при использовании модели безопасности Firebase. См. Раздел «Правила не являются фильтрами» в документации Firebase, а также эти предыдущие вопросы и ответы:

  • разрешение на защиту firebase не работает
  • правила firebase не работают
  • Как использовать правила Firebase только для разрешения определенных листовых узлов

Самое простое решение – разрешить чтение узла users :

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

И затем запрос на этом уровне:

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

Я получил это исключение, используя немного другой подход к чтению из моей базы данных, но именно так я решил проблему.

Прежде всего, правилам моей базы данных понравилось:

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

Раньше, чтобы писать в студенческую базу данных, я использовал этот код в своей работе:

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

Обратите внимание, как дочернее имя (ученик) соответствует имени дочернего элемента в правилах данных firebase?

Теперь, чтобы прочитать данные этого пользователя, я сделал следующее:

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

Я получил разрешение исключить исключение, если только:

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

Проблема в том, что у 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; } 
  • Установленное соединение было прервано программным обеспечением вашей главной машины
  • Как получить токен доступа после входа пользователя из Gmail в Android?
  • Как открыть Gmail Compose при нажатии кнопки в приложении Android?
  • Скрыть TabLayout на прокрутке содержимого вместо ToolBar
  • Получить имя файла и путь от URI от медиастора
  • Как реализовать устаревшие методы уведомления
  • Доступ к изображениям из приложения «Картинки» в приложении для Android
  • BroadcastReceiver + SMS_RECEIVED
  • Навигационный ящик полупрозрачный поверх строки состояния не работает
  • Какую мобильную платформу я должен начать изучать?
  • Как использовать интерфейс для связи между двумя действиями
  • Давайте будем гением компьютера.