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

Javascript 如何检测用户是否已登录Firebase?,javascript,web,firebase,firebase-authentication,Javascript,Web,Firebase,Firebase Authentication,我在谷歌登录的javascript文件中使用firebase节点api firebase.initializeApp(config); let provider = new firebase.auth.GoogleAuthProvider(); firebase.auth().signInWithPopup(provider); 这很好,用户可以使用他的谷歌凭证登录。当用户再次访问页面时,弹出窗口将再次打开,但由于用户已登录,弹出窗口将关闭,而无需用户进行任何交互。在提示弹出窗口之前,是否有方

我在谷歌登录的javascript文件中使用firebase节点api

firebase.initializeApp(config);
let provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider);
这很好,用户可以使用他的谷歌凭证登录。当用户再次访问页面时,弹出窗口将再次打开,但由于用户已登录,弹出窗口将关闭,而无需用户进行任何交互。在提示弹出窗口之前,是否有方法检查是否已经有登录用户?

使用
Firebase.getAuth()
。它返回Firebase客户端的当前状态。否则返回值为
null
以下是文档:

您必须添加身份验证状态更改观察者

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

您还可以检查是否存在currentUser


首先导入以下内容

import Firebase
import FirebaseAuth
然后


在这种情况下,不需要使用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”

这就是你所需要的


关于

当页面开始加载时,不可能判断用户是否将被签名,但是有一个解决办法

您可以将上次身份验证状态记忆到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路由器一起使用。我将上面的代码放入我的应用程序根组件的
componentDidMount
。在那里,在渲染中,我有一些
PrivateRoutes

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

...
这就是我的私密路线的实现方式:

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}}}
    // />
导出默认函数PrivateRoute(props){
返回firebase.auth().currentUser!=null
? 
:localStorage.getItem('myPage.expectSignIn')
//若预期用户自动登录,则显示微调器,否则重定向到登录页面。
? 
: (
正在重定向到登录页面。
{location.replace(`/login?from=${props.path}`)}
)
}
//使用路由器重定向而不是location.replace
// 

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

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

收件人:因为firebase既没有列出也没有推荐。你可以把这种方法称为非官方的方法。这意味着,如果firebase稍后更改其内部工作,则此方法可能无法工作。或者简而言之。使用风险自负!:)

这是有效的:

异步函数IsLoggedIn():Promise{ 试一试{ 等待新的承诺((决定,拒绝)=> app.auth().onAuthStateChanged( 用户=>{ 如果(用户){ //用户已登录。 解析(用户) }否则{ //没有用户登录。 拒绝('没有用户登录') } }, //防止控制台错误 错误=>拒绝(错误) ) ) 返回真值 }捕获(错误){ 返回错误 } }
如果您允许匿名用户以及通过电子邮件登录的用户,您可以使用
firebase.auth().currentUser.isAnonymous
,它将返回
true
false
,从技术上讲,承诺有三种可能性:

//1)最佳选项,因为它等待用户。。。
const isLoggedIn:any=等待新承诺((解决:any,拒绝:any)=>
this.afa.onAuthStateChanged((用户:any)=>
解析(用户),(e:any)=>拒绝(e));
console.log(isLoggedIn);
//2)可能会遇到注销状态问题。。。
const isLoggedIn2=等待this.afa.authState.pipe(first()).toPromise();
console.log(isLoggedIn2);
//3)在加载用户之前,技术上有第三个选项“未知”。。。
const isLoggedIn3=等待this.afa.currentUser;
console.log(isLoggedIn3);
//然后使用1、2或3执行类似操作(取决于您的需要):
如果(!!isLoggedIn){
//登录
}

另外请注意,该示例是有角度的,但您可以将
this.afa
替换为
firebase.auth()

已弃用,请避免
firebase.getAuth()
这对我来说是不一致的。使用onAuthStateChanged,是否有办法判断用户是否是新用户?是的,但不能通过
onAuthStateChanged
。这是在4.6.0中添加的:您可以从登录方法或从
currentUser.metadata
(上次登录时间和创建时间)获取它。@bojeil我认为此方法有一个警告。您可以将此代码放在一个页面上,即使您不在该页面上,它也会触发。当AuthState更改时,它将触发。如果它在其他页面上发生变化,当你不希望它发生变化时,它就会被触发。至少,我现在就是这样。这将在其他选项卡上检测登录事件。它按预期工作。Firebase Auth跨windows传播登录事件。即使在立即登录后,这也会为我返回null。这很奇怪,它对我有效,可能是因为Auth是异步的并且uCurrentUser_uuu尚未更新。从文档中可以看出:currentUser也可能为null,因为Auth
<Router>
  <Switch>
    <PrivateRoute
      exact path={routes.DASHBOARD}
      component={pages.Dashboard}
    />
...
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}}}
    // />