Wie erkenne ich, ob ein Benutzer bereits in Firebase angemeldet ist?


102

Ich verwende die Firebase-Knoten-API in meinen Javascript-Dateien für die Google-Anmeldung.

firebase.initializeApp(config);
let provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider);

Dies funktioniert einwandfrei und der Nutzer kann sich mit seinen Google-Anmeldeinformationen anmelden. Wenn der Benutzer die Seite erneut besucht, wird das Popup erneut geöffnet. Da er sich jedoch bereits angemeldet hat, wird das Popup geschlossen, ohne dass der Benutzer interagieren muss. Gibt es eine Möglichkeit zu überprüfen, ob bereits ein Benutzer angemeldet ist, bevor das Popup angezeigt wird?

Antworten:


113

https://firebase.google.com/docs/auth/web/manage-users

Sie müssen einen Beobachter für die Änderung des Authentifizierungsstatus hinzufügen.

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  } else {
    // No user is signed in.
  }
});

3
Das ist für mich inkonsistent. stackoverflow.com/questions/39395158/…
Dan P.

2
Gibt es eine Möglichkeit, mithilfe von onAuthStateChanged festzustellen, ob ein Benutzer neu ist?
Brennan

Ja, aber nicht durch onAuthStateChanged. Dies wurde in 4.6.0 hinzugefügt: firebase.google.com/support/release-notes/js#4.6.0 Sie können es von der Anmeldemethode oder von currentUser.metadata(letzte Anmeldezeit und Erstellungszeit) abrufen ...
Bojeil

@bojeil Ich denke, es gibt eine Einschränkung bei dieser Methode. Sie können diesen Code auf eine Seite setzen und er wird auch dann ausgelöst, wenn Sie sich nicht auf dieser Seite befinden. Es wird ausgelöst, wenn sich der AuthState ändert. Wenn es sich auf anderen Seiten ändert, wird es effektiv ausgelöst, wenn Sie es nicht möchten. Zumindest passiert mir das gerade.
Thevengefulco

1
Dadurch werden Anmeldeereignisse auf anderen Registerkarten erkannt. Es funktioniert wie vorgesehen. Firebase Auth verbreitet Anmeldeereignisse über Fenster hinweg.
Bojeil

82

Sie können auch überprüfen, ob ein aktueller Benutzer vorhanden ist

var user = firebase.auth().currentUser;

if (user) {
  // User is signed in.
} else {
  // No user is signed in.
}

8
Dies gibt für mich auch nach einer sofortigen Anmeldung null zurück.
Aarmora

8
Das ist seltsam, es funktioniert für mich, vielleicht liegt das Problem daran, dass auth asynchron ist und _ currentUser_ noch nicht aktualisiert wurde.
Daniel Passos

1
Aus den Dokumenten: currentUser kann auch null sein, da das Auth-Objekt noch nicht initialisiert wurde. Wenn Sie einen Beobachter verwenden, um den Anmeldestatus des Benutzers zu verfolgen, müssen Sie diesen Fall nicht behandeln.
Cheshireoctopus

Darauf kann man sich nicht verlassen. Siehe offizielle Dokumente: "Es gibt einige Fälle, in denen getCurrentUser eine Nicht-Null zurückgibt ..."
Andrew

Wenn Sie null erhalten, liegt dies wahrscheinlich daran, dass es noch nicht initialisiert wurde.
Arnaldo Capo

28

Es ist nicht möglich zu sagen , ob ein Benutzer wird unterzeichnet werden , wenn ein Laden der Seite beginnt, gibt es eine Arbeit um , obwohl ist.

Sie können den letzten Authentifizierungsstatus in localStorage speichern, um ihn zwischen Sitzungen und zwischen Registerkarten beizubehalten.

Wenn die Seite geladen wird, können Sie optimistisch davon ausgehen, dass der Benutzer automatisch neu angemeldet wird, und den Dialog verschieben, bis Sie sicher sind (dh nach einem onAuthStateChangedBrand). Andernfalls localStoragekönnen Sie den Dialog sofort anzeigen, wenn der Schlüssel leer ist.

Das Firebase- onAuthStateChangedEreignis wird ungefähr 2 Sekunden nach dem Laden der Seite ausgelöst.

// User signed out in previous session, show dialog immediately because there will be no auto-login
if (!localStorage.getItem('myPage.expectSignIn')) showDialog() // or redirect to sign-in page

firebase.auth().onAuthStateChanged(user => {
  if (user) {
    // User just signed in, we should not display dialog next time because of firebase auto-login
    localStorage.setItem('myPage.expectSignIn', '1')
  } else {
    // User just signed-out or auto-login failed, we will show sign-in form immediately the next time he loads the page
    localStorage.removeItem('myPage.expectSignIn')

    // Here implement logic to trigger the login dialog or redirect to sign-in page, if necessary. Don't redirect if dialog is already visible.
    // e.g. showDialog()
  }
})



Ich benutze dies mit React und React -Router . Ich habe den obigen Code in componentDidMountmeine App-Stammkomponente eingefügt. Dort im Render habe ich welchePrivateRoutes

<Router>
  <Switch>
    <PrivateRoute
      exact path={routes.DASHBOARD}
      component={pages.Dashboard}
    />
...

Und so wird meine PrivateRoute implementiert:

export default function PrivateRoute(props) {
  return firebase.auth().currentUser != null
    ? <Route {...props}/>
    : localStorage.getItem('myPage.expectSignIn')
      // if user is expected to sign in automatically, display Spinner, otherwise redirect to login page.
      ? <Spinner centered size={400}/>
      : (
        <>
          Redirecting to sign in page.
          { location.replace(`/login?from=${props.path}`) }
        </>
      )
}

    // Using router Redirect instead of location.replace
    // <Redirect
    //   from={props.path}
    //   to={{pathname: routes.SIGN_IN, state: {from: props.path}}}
    // />

Glaubst du, du könntest mir dabei helfen? Ich habe versucht, die automatische Anmeldeumleitung, die Sie oben in Ihrer Antwort haben, zu verwenden, und jetzt kann ich sie scheinbar nicht mehr entfernen. Ich habe meinen lokalen Speicher vollständig gelöscht und kann aufgrund der ständigen Weiterleitungen immer noch nicht auf meine abgemeldete Firebase-Site zugreifen.
Hego64

@ hego64 Hast du dich tatsächlich von deiner Firebase-App abgemeldet? Diese Lösung führt keine Anmeldung durch. Sie ermöglicht das Überspringen des Anmeldeformulars nur, wenn sich der Benutzer in der vorherigen Sitzung nicht abgemeldet hat. / EDIT: Befindest du dich in einer Umleitungsschleife? Ich werde die Antwort aktualisieren.
Qwerty

Ja, ich hätte klarer sein sollen, ich steckte in einer Umleitungsschleife. Ich habe mich abgemeldet und anstatt zur App zurückzukehren, wurde ich direkt zur Anmeldeseite zurückgeführt. Ich konnte das Problem beheben, indem ich auf eine frühere Bereitstellung zurückgesetzt habe. Abgesehen davon war ich mir nicht sicher, was ich tun sollte, um das Problem zu beheben.
Hego64

1
@ hego64 Benutzer, die nicht angemeldet sind, sollten nicht in der Lage sein, frei herumzulaufen. Daher ist die Umleitung zur Anmeldeseite korrekt. Wenn jedoch Routen ohne Authentifizierung verfügbar sind, müssen Sie die Logik auf den Router verschieben oder stattdessen bestimmte Routen, ähnlich wie in meinem PrivateRoute-Wrapper-Beispiel. Wenn sich der Benutzer auf einer eingeschränkten Seite befindet und sich abmeldet, wird er zur Anmeldeseite weitergeleitet. Auf Ihren anderen Routen wird diese Logik nicht implementiert.
Qwerty

Ich war ein bisschen dabei ... diese Methode funktioniert ziemlich gut. Danke dir.
spetz83

17

In diesem Szenario muss die Funktion onAuthStateChanged () nicht verwendet werden.

Sie können leicht feststellen, ob der Benutzer angemeldet ist oder nicht, indem Sie Folgendes ausführen:

var user = firebase.auth().currentUser;

Für diejenigen, die mit dem Problem der "Rückgabe von Null" konfrontiert sind, liegt dies nur daran, dass Sie nicht auf den Abschluss des Firebase-Aufrufs warten.

Angenommen, Sie führen die Anmeldeaktion auf Seite A aus und rufen dann Seite B auf. Auf Seite B können Sie den folgenden JS-Code aufrufen, um das erwartete Verhalten zu testen:

  var config = {
    apiKey: "....",
    authDomain: "...",
    databaseURL: "...",
    projectId: "..",
    storageBucket: "..",
    messagingSenderId: ".."
  };
  firebase.initializeApp(config);

    $( document ).ready(function() {
        console.log( "testing.." );
        var user = firebase.auth().currentUser;
        console.log(user);
    });

Wenn der Benutzer protokolliert ist, enthält "var user" die erwartete JSON-Nutzlast. Wenn nicht, ist sie nur "null".

Und das ist alles was du brauchst.

Grüße


3
@ Mauricio Silvestre ist es? Verwenden von firebase.auth.currentUserRetouren undefiniert, ob ich angemeldet bin oder nicht. Nur auth () gibt das richtige Ergebnis zurück, wenn ich angemeldet bin.
tsujp

5

Eine andere Möglichkeit besteht darin, dasselbe zu verwenden, was Firebase verwendet.

Wenn sich der Benutzer beispielsweise anmeldet, speichert Firebase die folgenden Details im lokalen Speicher. Wenn der Benutzer zur Seite zurückkehrt, verwendet Firebase dieselbe Methode, um festzustellen, ob der Benutzer automatisch angemeldet werden soll.

Geben Sie hier die Bildbeschreibung ein

ATTN: Da dies von Firebase weder aufgeführt noch empfohlen wird. Sie können diese Methode als inoffizielle Methode bezeichnen. Das heißt, später, wenn Firebase ihre innere Arbeitsweise ändert, funktioniert diese Methode möglicherweise nicht. Oder kurz gesagt. Benutzung auf eigene Gefahr! :) :)


5

Das funktioniert:

async function IsLoggedIn(): Promise<boolean> {
  try {
    await new Promise((resolve, reject) =>
      app.auth().onAuthStateChanged(
        user => {
          if (user) {
            // User is signed in.
            resolve(user)
          } else {
            // No user is signed in.
            reject('no user logged in')
          }
        },
        // Prevent console error
        error => reject(error)
      )
    )
    return true
  } catch (error) {
    return false
  }
}

1

Wenn Sie sowohl anonyme als auch mit E-Mail angemeldete Benutzer zulassen, können Sie diese verwenden firebase.auth().currentUser.isAnonymous, die entweder trueoder zurückgeben false.



-3

Importieren Sie zuerst Folgendes

import Firebase
import FirebaseAuth

Dann

    // Check if logged in
    if (Auth.auth().currentUser != null) {
      // User is logged in   
    }else{
      // User is not logged in
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.