Come faccio a rilevare se un utente ha già effettuato l'accesso a Firebase?


103

Sto utilizzando l'API del nodo Firebase nei miei file javascript per l'accesso a Google.

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

Funziona bene e l'utente è in grado di accedere con le proprie credenziali di Google. Quando l'utente visita nuovamente la pagina, il popup si apre nuovamente ma poiché ha già effettuato l'accesso, il popup si chiude senza richiedere alcuna interazione da parte dell'utente. C'è un modo per verificare se c'è già un utente connesso prima di visualizzare il popup?

Risposte:


113

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

Devi aggiungere un osservatore del cambiamento dello stato di autenticazione.

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

3
Questo è incoerente per me. stackoverflow.com/questions/39395158/…
Dan P.

2
Usando onAuthStateChanged, c'è un modo per sapere se un utente è nuovo?
Brennan

Sì, ma non attraverso onAuthStateChanged. Questo è stato aggiunto nella 4.6.0: firebase.google.com/support/release-notes/js#4.6.0 Puoi ottenerlo dal metodo di accesso o da currentUser.metadata(ora dell'ultimo accesso e ora di creazione) ...
bojeil

@bojeil Penso che ci sia un avvertimento a questo metodo. Puoi mettere questo codice su una pagina e si attiverà anche quando non sei su quella pagina. Si attiva quando l'AuthState cambia. Se cambia su altre pagine, lo farai effettivamente scattare quando non lo desideri. Almeno, è quello che mi sta succedendo adesso.
thevengefulco

1
Questo rileverà gli eventi di accesso in altre schede. Funziona come previsto. Firebase Auth propaga gli eventi di accesso tra le finestre.
bojeil

82

Puoi anche controllare se c'è un utente corrente

var user = firebase.auth().currentUser;

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

8
Questo restituisce null per me anche dopo un accesso immediato.
Aarmora

8
È strano, per me funziona, forse il problema è perché auth è asincrono e _ currentUser_ non è stato ancora aggiornato.
Daniel Passos

1
Dalla documentazione: currentUser potrebbe anche essere nullo perché l'inizializzazione dell'oggetto auth non è stata completata. Se utilizzi un osservatore per tenere traccia dello stato di accesso dell'utente, non è necessario che tu gestisca questo caso.
cheshireoctopus

Non puoi fare affidamento su di esso. Consulta i documenti ufficiali: "Ci sono alcuni casi in cui getCurrentUser restituirà un valore non nullo ..."
Andrew

Se ottieni null, probabilmente è perché non è stato ancora inizializzato.
Arnaldo Capo

28

Non è possibile dire se un utente verrà firmato quando una pagina inizia a caricarsi, c'è comunque da aggirare.

È possibile memorizzare l'ultimo stato di autenticazione su localStorage per mantenerlo tra le sessioni e tra le schede.

Quindi, quando la pagina inizia a caricarsi, puoi assumere ottimisticamente che l'utente accederà di nuovo automaticamente e posticipare la finestra di dialogo finché non sarai sicuro (cioè dopo gli onAuthStateChangedincendi). Altrimenti, se la localStoragechiave è vuota, puoi mostrare subito la finestra di dialogo.

L' onAuthStateChangedevento Firebase si attiverà circa 2 secondi dopo il caricamento di una pagina.

// 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()
  }
})



Lo sto usando con React e React -router . Ho inserito il codice sopra nel componentDidMountmio componente root dell'app. Lì, nel render, ne ho alcuniPrivateRoutes

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

Ed è così che viene implementato il mio PrivateRoute:

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}}}
    // />

Pensi di potermi aiutare con questo? Ho provato il reindirizzamento del login automatico che hai nella parte superiore della tua risposta e ora non riesco a rimuoverlo. Ho svuotato completamente la mia memoria locale e non riesco ancora ad accedere al mio sito Firebase disconnesso a causa dei continui reindirizzamenti.
hego64

@ hego64 Ti sei effettivamente disconnesso dalla tua app Firebase? Questa soluzione non esegue il login. Consente solo di saltare il modulo di accesso se l'utente non si è disconnesso nella sessione precedente. / EDIT: sei in un ciclo di reindirizzamento? Aggiornerò la risposta.
Qwerty

Sì, avrei dovuto essere più chiaro, ero bloccato in un ciclo di reindirizzamento. Mi disconnettevo e invece di tornare all'app, tornavo direttamente alla pagina di accesso. Sono stato in grado di risolverlo tornando a una distribuzione precedente, ma a parte questo non ero sicuro di cosa fare per risolvere il problema.
hego64

1
@ hego64 Gli utenti che non hanno effettuato l'accesso non dovrebbero essere in grado di muoversi liberamente ogni giorno, quindi il reindirizzamento alla pagina di accesso è corretto, ma se ci sono percorsi disponibili senza autenticazione, è necessario spostare la logica sul router o percorsi particolari invece, proprio come nel mio esempio di wrapper PrivateRoute. Quindi, se l'utente si trova su una pagina con restrizioni e si disconnette, verrà reindirizzato alla pagina di accesso. Gli altri percorsi non avranno questa logica implementata.
Qwerty

Sono rimasto bloccato su questo per un po '... questo metodo funziona abbastanza bene. Grazie.
spetz83

17

Non è necessario utilizzare la funzione onAuthStateChanged () in questo scenario.

Puoi facilmente rilevare se l'utente è registrato o meno eseguendo:

var user = firebase.auth().currentUser;

Per coloro che affrontano il problema della "restituzione di valori nulli", è solo perché non stai aspettando il completamento della chiamata Firebase.

Supponiamo che tu esegua l'azione di login sulla Pagina A e poi invoca la Pagina B, sulla Pagina B puoi chiamare il seguente codice JS per testare il comportamento previsto:

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

Se l'utente è registrato, "var user" conterrà il payload JSON previsto, in caso contrario sarà solo "null"

E questo è tutto ciò di cui hai bisogno.

Saluti


3
@Mauricio Silvestre è vero? Utilizzo di firebase.auth.currentUserritorni indefinito indipendentemente dal fatto che sia stato effettuato l'accesso. Solo auth () restituisce il risultato corretto all'accesso.
tsujp

5

Un altro modo è usare la stessa cosa che usa Firebase.

Ad esempio, quando l'utente accede, Firebase memorizza i dettagli di seguito nella memoria locale. Quando l'utente torna alla pagina, firebase utilizza lo stesso metodo per identificare se l'utente deve accedere automaticamente.

inserisci qui la descrizione dell'immagine

ATTENZIONE: poiché questo non è né elencato né consigliato da Firebase. Puoi chiamare questo metodo un modo non ufficiale per farlo. Ciò significa che in seguito se Firebase cambia il proprio funzionamento interno, questo metodo potrebbe non funzionare. O in breve. Utilizzare a proprio rischio! :)


5

Funziona:

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

Se stai consentendo agli utenti anonimi e a quelli che hanno effettuato l'accesso con la posta elettronica, puoi utilizzare firebase.auth().currentUser.isAnonymous, che restituirà trueo false.



-3

Per prima cosa importa quanto segue

import Firebase
import FirebaseAuth

Poi

    // Check if logged in
    if (Auth.auth().currentUser != null) {
      // User is logged in   
    }else{
      // User is not logged in
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.