Как определить, вошел ли пользователь в Firebase?

104

Я использую api узла firebase в своих файлах javascript для входа в Google.

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

Это работает нормально, и пользователь может войти в систему со своими учетными данными Google. Когда пользователь снова посещает страницу, всплывающее окно открывается снова, но, поскольку он уже вошел в систему, всплывающее окно закрывается, не требуя какого-либо взаимодействия со стороны пользователя. Есть ли способ проверить, есть ли уже вошедший в систему пользователь, прежде чем запрашивать всплывающее окно?

Иофин Джозеф
источник

Ответы:

115

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

Вам нужно добавить наблюдателя за изменением состояния авторизации.

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  } else {
    // No user is signed in.
  }
});
Bojeil
источник
3
Для меня это непоследовательно. stackoverflow.com/questions/39395158/…
Дэн П.
2
Есть ли способ узнать, является ли пользователь новым, используя onAuthStateChanged?
Бреннан
Да, но не насквозь onAuthStateChanged. Это был добавлен в 4.6.0: firebase.google.com/support/release-notes/js#4.6.0 Вы можете получить его от входа в методе или currentUser.metadata(последний знак времени и времени создания) ...
bojeil
@bojeil Я думаю, что у этого метода есть предостережение. Вы можете поместить этот код на одну страницу, и он сработает, даже если вы не находитесь на этой странице. Он срабатывает при изменении AuthState. Если он изменится на других страницах, он будет срабатывать, когда вы этого не хотите. По крайней мере, это то, что сейчас со мной происходит.
thevengefulco
1
Это обнаружит события входа в систему на других вкладках. Работает как задумано. Firebase Auth распространяет события входа в Windows.
bojeil
85

Вы также можете проверить, есть ли текущий пользователь

var user = firebase.auth().currentUser;

if (user) {
  // User is signed in.
} else {
  // No user is signed in.
}
Даниэль Пассос
источник
8
Для меня это возвращает null даже после немедленного входа в систему.
Aarmora
8
Странно, у меня это работает, возможно, проблема в том, что auth асинхронный, а _ currentUser_ еще не обновлен.
Даниэль Пассос
1
Из документов: currentUser также может иметь значение null, потому что объект auth не завершил инициализацию. Если вы используете наблюдателя для отслеживания статуса входа пользователя, вам не нужно обрабатывать этот случай.
cheshireoctopus
На это нельзя положиться. См. Официальную документацию: «В некоторых случаях getCurrentUser возвращает ненулевое значение ...»
Эндрю
Если вы получаете null, вероятно, потому, что он еще не инициализирован.
Арнальдо Капо
28

Это не возможно сказать , является ли пользователь будет быть подписан , когда страница начинается загрузка, есть работа вокруг , хотя.

Вы можете запомнить последнее состояние аутентификации в localStorage, чтобы сохранять его между сеансами и между вкладками.

Затем, когда страница начинает загружаться, вы можете оптимистично предположить, что пользователь будет повторно авторизован автоматически, и отложить диалог до тех пор, пока вы не будете уверены (например, после onAuthStateChangedпожаров). В противном случае, если localStorageключ пуст, вы можете сразу показать диалог.

onAuthStateChangedСобытие firebase срабатывает примерно через 2 секунды после загрузки страницы.

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



Я использую это с React и response-router . Я поместил приведенный выше код в componentDidMountсвой корневой компонент приложения. Там, на рендере, у меня естьPrivateRoutes

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

И вот как реализован мой 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}}}
    // />
Qwerty
источник
Как вы думаете, вы могли бы мне с этим помочь? Я попробовал перенаправить автоматический вход в систему, указанную в верхней части вашего ответа, и теперь не могу его удалить. Я полностью очистил свое локальное хранилище, и я все еще не могу получить доступ к своему сайту firebase, вышедшему из системы из-за постоянных перенаправлений.
hego64
@ hego64 Вы действительно вышли из приложения firebase? Это решение не выполняет вход в систему. Оно позволяет пропустить форму входа только в том случае, если пользователь не вышел из системы в предыдущем сеансе. / EDIT: Вы находитесь в цикле перенаправления? Обновлю ответ.
Qwerty
Да, мне следовало быть более ясным, я застрял в цикле перенаправления. Я выхожу из системы, и вместо того, чтобы вернуться в приложение, меня сразу же переводили на страницу входа. Мне удалось исправить это, откатившись к предыдущему развертыванию, но в остальном я не был уверен, что делать, чтобы исправить проблему.
hego64
1
@ hego64 Пользователи, которые не вошли в систему, не должны иметь возможность свободно перемещаться, поэтому перенаправление на страницу входа в систему является правильным, но если есть маршруты, доступные без аутентификации, вы должны переместить логику на маршрутизатор или конкретные маршруты, как в моем примере оболочки PrivateRoute. Поэтому, если пользователь находится на странице с ограниченным доступом и выходит из системы, он будет перенаправлен на страницу входа. На других ваших маршрутах эта логика реализована не будет.
Qwerty
Я немного зациклился на этом ... этот метод работает очень хорошо. Спасибо.
spetz83
17

В этом сценарии нет необходимости использовать функцию onAuthStateChanged ().

Вы можете легко определить, вошел ли пользователь в систему или нет, выполнив:

var user = firebase.auth().currentUser;

Для тех, кто сталкивается с проблемой «возврата нуля», это просто потому, что вы не ждете завершения вызова firebase.

Предположим, вы выполняете действие входа в систему на странице A, а затем вызываете страницу B, на странице B вы можете вызвать следующий код JS для проверки ожидаемого поведения:

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

Если пользователь зарегистрирован, то «var user» будет содержать ожидаемую полезную нагрузку JSON, если нет, то это будет просто «null»

И это все, что вам нужно.

С уважением

Даниил Вукасович
источник
3
@ Маурисио Сильвестр? Использование firebase.auth.currentUserвозвращает undefined независимо от того, вошел ли я в систему или нет. Только auth () возвращает правильный результат, когда
вошел
6

Это работает:

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
  }
}
Бен Виндинг
источник
5

Еще один способ - использовать то же самое, что и firebase.

Например, когда пользователь входит в систему, firebase сохраняет указанные ниже данные в локальном хранилище. Когда пользователь возвращается на страницу, firebase использует тот же метод, чтобы определить, должен ли пользователь входить в систему автоматически.

введите описание изображения здесь

ВНИМАНИЕ: так как это не указано и не рекомендовано firebase. Вы можете назвать этот метод неофициальным способом сделать это. Это означает, что позже, если firebase изменит свою внутреннюю работу, этот метод может не работать. Или короче. Используйте на свой риск! :)

ravish.hacker
источник
1

Если вы разрешаете анонимным пользователям, а также тех, кто вошел в систему по электронной почте, вы можете использовать firebase.auth().currentUser.isAnonymous, что вернет либо trueили false.

Maudulus
источник
-1

использовать Firebase.getAuth(). Возвращает текущее состояние клиента Firebase. В противном случае возвращаемое значение: nullВот документы: https://www.firebase.com/docs/web/api/firebase/getauth.html

Muetzerich
источник
15
Устарело, избегайтеfirebase.getAuth()
Mazze 01
-3

Сначала импортируйте следующие

import Firebase
import FirebaseAuth

затем

    // Check if logged in
    if (Auth.auth().currentUser != null) {
      // User is logged in   
    }else{
      // User is not logged in
    }
Даниэль
источник