Bagaimana cara mendeteksi jika pengguna sudah masuk ke Firebase?

104

Saya menggunakan api node firebase di file javascript saya untuk login Google.

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

Ini berfungsi dengan baik dan pengguna dapat masuk dengan kredensial Google-nya. Saat pengguna mengunjungi halaman itu lagi, pop-up akan terbuka lagi tetapi karena dia sudah login, pop-up tersebut menutup tanpa memerlukan interaksi apa pun dari pengguna. Apakah ada cara untuk memeriksa apakah sudah ada pengguna yang login sebelum meminta popup?

Jophin Joseph
sumber

Jawaban:

115

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

Anda harus menambahkan pengamat perubahan status autentikasi.

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  } else {
    // No user is signed in.
  }
});
bojeil.dll
sumber
3
Ini tidak konsisten bagi saya. stackoverflow.com/questions/39395158/…
Dan P.
2
Dengan menggunakan onAuthStateChanged, apakah ada cara untuk mengetahui apakah seorang pengguna baru?
Brennan
Ya, tapi tidak lewat onAuthStateChanged. Ini ditambahkan di 4.6.0: firebase.google.com/support/release-notes/js#4.6.0 Anda bisa mendapatkannya dari metode masuk atau dari currentUser.metadata(waktu masuk terakhir dan waktu pembuatan) ...
bojeil
@ Bojeil Saya pikir ada peringatan untuk metode ini. Anda dapat meletakkan kode ini di satu halaman, dan itu akan memicu bahkan saat Anda tidak berada di halaman itu. Ini terpicu ketika AuthState berubah. Jika berubah di halaman lain, Anda akan secara efektif memicu saat Anda tidak menginginkannya. Setidaknya, itulah yang terjadi pada saya saat ini.
thevengefulco
1
Ini akan mendeteksi acara masuk di tab lain. Ini berfungsi sebagaimana mestinya. Firebase Auth menyebarkan peristiwa masuk di seluruh jendela.
bojeil
84

Anda juga dapat memeriksa apakah ada currentUser

var user = firebase.auth().currentUser;

if (user) {
  // User is signed in.
} else {
  // No user is signed in.
}
Daniel Passos
sumber
8
Ini mengembalikan nol untuk saya bahkan setelah login langsung.
Aarmora
8
Aneh, ini berfungsi untuk saya, mungkin masalahnya karena auth adalah async dan _ currentUser_ belum diperbarui.
Daniel Passos
1
Dari dokumen: currentUser mungkin juga null karena objek auth belum selesai menginisialisasi. Jika Anda menggunakan pengamat untuk melacak status masuk pengguna, Anda tidak perlu menangani kasus ini.
cheshireoctopus
Anda tidak bisa mengandalkannya. Lihat dokumen resmi: "Ada beberapa kasus di mana getCurrentUser akan mengembalikan bukan nol ..."
Andrew
Jika Anda mendapatkan null, itu mungkin karena belum diinisialisasi.
Arnaldo Capo
28

Tidak mungkin untuk mengetahui apakah pengguna akan masuk ketika halaman mulai memuat, ada solusi meskipun.

Anda dapat mengingat status autentikasi terakhir ke localStorage untuk mempertahankannya di antara sesi dan antar tab.

Kemudian, saat halaman mulai memuat, Anda dapat secara optimis mengasumsikan bahwa pengguna akan masuk kembali secara otomatis dan menunda dialog sampai Anda dapat yakin (yaitu setelah onAuthStateChangeddiaktifkan). Jika tidak, jika localStoragekuncinya kosong, Anda dapat langsung menampilkan dialog.

Peristiwa firebase onAuthStateChangedakan aktif sekitar 2 detik setelah halaman dimuat.

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



Saya menggunakan ini dengan React dan react-router . Saya memasukkan kode di atas ke componentDidMountdalam komponen root Aplikasi saya. Di sana, dalam render, saya punya beberapaPrivateRoutes

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

Dan inilah cara PrivateRoute saya diterapkan:

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}}}
    // />
Qwerty
sumber
Apakah Anda pikir Anda bisa membantu saya dengan ini? Saya mencoba pengalihan masuk otomatis yang Anda miliki di bagian atas jawaban Anda, dan sekarang sepertinya saya tidak dapat menghapusnya. Saya telah mengosongkan penyimpanan lokal saya sepenuhnya dan saya masih tidak dapat mengakses situs firebase saya saat keluar karena pengalihan terus-menerus.
hego64
@ hego64 Pernahkah Anda benar-benar keluar dari aplikasi firebase? Solusi ini tidak melakukan login. Ini hanya memungkinkan untuk melewati formulir login jika pengguna tidak keluar di sesi sebelumnya. / EDIT: Apakah Anda dalam loop pengalihan? Saya akan memperbarui jawabannya.
Qwerty
Ya, saya seharusnya lebih jelas, saya terjebak dalam loop pengalihan. Saya akan logout, dan bukannya kembali ke aplikasi, saya langsung dibawa kembali ke halaman login. Saya dapat memperbaikinya dengan mengembalikan ke penerapan sebelumnya, tetapi selain itu saya tidak yakin apa yang harus dilakukan untuk memperbaiki masalah tersebut.
hego64
1
@ hego64 Pengguna yang tidak masuk seharusnya tidak dapat berjalan-jalan dengan bebas anwyay, jadi pengalihan ke halaman log-in benar, tetapi jika ada rute yang tersedia tanpa otentikasi, Anda harus memindahkan logika ke router atau rute tertentu, seperti pada contoh pembungkus PrivateRoute saya. Jadi jika pengguna berada di halaman terbatas dan keluar, maka mereka akan diarahkan ke halaman masuk. Rute Anda yang lain tidak akan menerapkan logika ini.
Qwerty
Saya terjebak pada ini sebentar ... metode ini bekerja dengan cukup baik. Terima kasih.
spetz83
17

Tidak perlu menggunakan fungsi onAuthStateChanged () dalam skenario ini.

Anda dapat dengan mudah mendeteksi apakah pengguna masuk atau tidak dengan menjalankan:

var user = firebase.auth().currentUser;

Bagi mereka yang menghadapi masalah "mengembalikan null", itu hanya karena Anda tidak menunggu panggilan firebase selesai.

Misalkan Anda melakukan tindakan login pada Halaman A dan kemudian Anda memanggil Halaman B, di Halaman B Anda dapat memanggil kode JS berikut untuk menguji perilaku yang diharapkan:

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

Jika pengguna login maka "var user" akan berisi payload JSON yang diharapkan, jika tidak, maka hanya "null"

Dan hanya itu yang Anda butuhkan.

Salam

Daniel Vukasovich
sumber
3
@ Mauricio Silvestre apakah itu? Menggunakan firebase.auth.currentUserpengembalian tidak ditentukan apakah saya masuk atau tidak. Hanya auth () yang mengembalikan hasil yang benar saat masuk.
tsujp
5

Cara lainnya adalah menggunakan hal yang sama dengan yang digunakan firebase.

Misalnya saat pengguna masuk, firebase menyimpan detail di bawah ini di penyimpanan lokal. Saat pengguna kembali ke halaman, firebase menggunakan metode yang sama untuk mengidentifikasi apakah pengguna harus login secara otomatis.

masukkan deskripsi gambar di sini

PERHATIAN: Karena ini tidak terdaftar atau direkomendasikan oleh firebase. Anda dapat menyebut metode ini sebagai cara tidak resmi untuk melakukan ini. Yang berarti nanti jika firebase mengubah kerja dalamnya, metode ini mungkin tidak berfungsi. Atau singkatnya. Gunakan dengan resiko Anda sendiri! :)

ravish.hacker
sumber
5

Ini bekerja:

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
  }
}
Ben Winding
sumber
1

Jika Anda mengizinkan pengguna anonim serta mereka yang masuk dengan email, Anda dapat menggunakan firebase.auth().currentUser.isAnonymous, yang akan mengembalikan trueatau false.

maudulus
sumber
-1

gunakan Firebase.getAuth(). Ini mengembalikan status klien Firebase saat ini. Jika tidak, nilai kembaliannya adalah. nullBerikut dokumentasinya: https://www.firebase.com/docs/web/api/firebase/getauth.html

muetzerich.dll
sumber
15
Tidak berlaku lagi, hindarifirebase.getAuth()
Mazze
-3

Impor pertama yang berikut ini

import Firebase
import FirebaseAuth

Kemudian

    // Check if logged in
    if (Auth.auth().currentUser != null) {
      // User is logged in   
    }else{
      // User is not logged in
    }
Daniel
sumber