如何检测用户是否已经登录Firebase?


104

我在我的JavaScript文件中使用firebase节点api进行Google登录。

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

这可以正常工作,并且用户可以使用他的Google凭据登录。当用户再次访问该页面时,弹出窗口会再次打开,但是由于他已经登录,因此该弹出窗口将关闭,而无需用户进行任何交互。在提示弹出窗口之前,有什么方法可以检查是否已经有一个登录用户?

Answers:


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

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

84

您还可以检查是否有currentUser

var user = firebase.auth().currentUser;

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

8
即使在立即登录后,这也为我返回null。
Aarmora

8
奇怪,它对我有用,也许问题是因为auth是异步的,并且_ currentUser_尚未更新。
Daniel Passos

1
从docs:currentUser也可能为null,因为auth对象尚未完成初始化。如果使用观察者来跟踪用户的登录状态,则无需处理这种情况。
cheshireoctopus

你不能依靠它。请参阅官方文档:“在某些情况下,getCurrentUser将返回非null ...”
Andrew

如果您得到的是null,则可能是因为尚未初始化。
阿纳尔多·卡波

28

这是不可能的,告诉用户是否在页面开始加载签名,还有一个工作,虽然各地。

您可以将上一个身份验证状态存储到localStorage中,以在会话之间和选项卡之间持久保存该身份验证

然后,当页面开始加载时,您可以乐观地假设用户将自动重新登录并推迟对话框,直到您确定(即onAuthStateChanged触发后)为止。否则,如果localStorage键为空,则可以立即显示对话框。

页面加载后,firebase onAuthStateChanged事件将在大约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()
  }
})



我在Reactreact-router上使用它。我将上面的代码放入componentDidMount我的App根组件中。那里,在渲染中,我有一些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}}}
    // />

您认为您可以帮我吗?我尝试了答案顶部的自动登录重定向,现在似乎无法删除它。我已经彻底清除了本地存储,由于不断的重定向,我仍然无法访问注销的Firebase网站。
hego64

@ hego64您实际上已经注销了Firebase应用程序吗?此解决方案不执行登录。仅当用户未在上一个会话中注销时,才允许跳过登录表单。/编辑:您是否处于重定向循环中?我将更新答案。
Qwerty

是的,我应该更加清楚,我陷入了重定向循环。我将注销,而不是直接回到应用程序,而是直接回到了登录页面。我可以通过回滚到以前的部署来解决此问题,但除此之外,我不确定该如何解决。
hego64

1
@ hego64未登录的用户应该不能自由地走来走去,因此重定向到登录页面是正确的,但是如果存在未经身份验证的可用路由,则必须将逻辑移至路由器或特定路由,就像我的PrivateRoute包装器示例中一样。因此,如果用户位于受限页面上并退出,则他们将被重定向到登录页面。您的其他路线将不会实现此逻辑。
Qwerty

我对此有点卡住...这种方法效果很好。谢谢。
spetz83

17

在这种情况下,无需使用onAuthStateChanged()函数。

您可以通过执行以下命令轻松检测用户是否已登录:

var user = firebase.auth().currentUser;

对于那些面临“返回null”问题的人来说,这仅仅是因为您没有等待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
@Mauricio Silvestre是吗?使用firebase.auth.currentUser
return会

5

另一种方法是使用与Firebase相同的东西。

例如,当用户登录时,firebase将以下详细信息存储在本地存储中。当用户返回页面时,firebase使用相同的方法来确定用户是否应该自动登录。

在此处输入图片说明

ATTN:因为Firebase既没有列出也没有建议这样做。您可以将此方法称为非正式方法。这意味着以后如果Firebase更改其内部工作,则此方法可能无法工作。或总之。使用风险自负!:)


5

这有效:

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

如果您允许匿名用户以及使用电子邮件登录的用户,则可以使用firebase.auth().currentUser.isAnonymous,它们将返回truefalse



-3

首先导入以下

import Firebase
import FirebaseAuth

然后

    // Check if logged in
    if (Auth.auth().currentUser != null) {
      // User is logged in   
    }else{
      // User is not logged in
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.