android - Firebase-Berechtigung beim Lesen von Daten nach der Authentifizierung verweigert



firebase-security firebase-realtime-database (2)

Ich bin neu bei Firebase. Ich habe den Benutzer mit E-Mail und Passwort authentifiziert -

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

Aber nach der Authentifizierung, wenn ich die Daten lese, wird mir die 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());
        }
    });
}

Dies sind die Firebase-Regeln.

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

https://src-bin.com


Answer #1

Das Berechtigungsmodell von Firebase ermöglicht dem Benutzer nur den Zugriff auf Daten, auf die Sie ausdrücklich zugreifen. Da Sie in Ihren Sicherheitsregeln nur Zugriff auf /users/$uid , kann der Benutzer nicht von root / lesen. Die Firebase-Dokumentation behandelt dies unter "Regelkaskade" .

Sie möchten anscheinend Sicherheitsregeln zum Filtern von Daten verwenden, was mit dem Sicherheitsmodell von Firebase nicht möglich ist. Weitere Informationen finden Sie im Abschnitt "Regeln sind keine Filter" in der Firebase-Dokumentation sowie in den folgenden Fragen und Antworten:

Die einfachste Lösung besteht darin, das Lesen des users zuzulassen:

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

Und dann auf dieser Ebene abfragen:

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

Answer #2

Das Problem ist, dass Firebase einen Fehler aufweist. Nach der Authentifizierung müssen Sie warten, bis der Benutzer in FirebaseAuth angezeigt wird, und können ihn dann verwenden.

Was ich getan habe, ist darauf gewartet, dass es so aussieht

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

Wo

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