有时 firebase.auth().onAuthStateChanged 在我刷新页面时返回 null 用户
Posted
技术标签:
【中文标题】有时 firebase.auth().onAuthStateChanged 在我刷新页面时返回 null 用户【英文标题】:Sometimes firebase.auth().onAuthStateChanged returns user of null when I refresh the page 【发布时间】:2018-11-13 23:34:13 【问题描述】:前提条件
$npm install --save firebase@4.11.0
问题
我在我的 Web 应用程序上使用 firebase 身份验证。
在我的应用程序中,我为客户端 js 实现了onAuthStateChanged
,如下所示。
firebase.auth().onAuthStateChanged((user) =>
if(user)
//logged in
else
//do sth
);
登录后,我确认此方法将返回实际用户obj,但如果我刷新页面,则用户可能为空。 奇怪的是,有时用户不会为空。 恐怕调用onAuthStateChanged会有一些限制,但目前我不知道。
我应该如何处理这个问题?
更新
让我分享我的最小示例。
我的应用正在使用 express.js。
有两个 URL,如下所示。
/login
/main
在登录页面中,我实现了身份验证方法。 如果登录成功完成,则用户将被重定向到'/main'。
//login.js
import firebase from 'firebase';
var config = ...;
firebase.initializeApp(config);
var provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider)
.then((result) =>
return result.user.getIdToken(true);
).then((idToken) =>
if(idToken)
location.href = '/main';
);
在主页面中,没有登录方法。 main.js 只是检查用户是否登录。
//main.js
import firebase from 'firebase';
var config = ...;
firebase.initializeApp(config);
firebase.auth().onAuthStateChanged((user) =>
if (user)
//initialize main page.
else
location.href = '/login';
我认为登录状态存储在 Web 浏览器的 LocalStorage 中。
这意味着,在完成 main.js 的加载后,onAuthStateChanged 将使用用户信息自动触发,但不会像我预期的那样工作。
我确信登录信息的持久性是正确的,因为官方文档说默认设置是 LOCAL
用于 web 客户端。
https://firebase.google.com/docs/auth/web/auth-state-persistence
我的问题
我应该用另一种方式实现 onAuthStateChanged 吗? 重新加载后如何确保用户已登录?
例如
import $ from 'jquery';
$(document).on('ready', () =>
onAuthStateChanged((user) => ...);
);
或者你能告诉我正确的方法吗?
解决方法
如果返回 null,我决定删除会话并设置重定向到登录页面。这不是解决方案,而是当前的解决方法...
【问题讨论】:
.onAuthStateChanged
是异步的,在页面加载/刷新时为微秒解析 null。这就是它的工作原理。您可以将 loader 的 gif 变灰或放置。
你的意思是说,在重新加载后,第一个onAuthStateChanged
事件将被空用户触发,几秒钟后该事件将被实际用户信息重新触发?我实现了加载 gif 10 秒,直到加载完成,就像你提到的那样,但是,不幸的是,我的 onAuthStateChanged
只被空用户触发一次......
在另一个浏览器上尝试网络应用/您的应用。我注意到,例如,如果您将 Firefox 设置为从不记住历史记录(可能是关闭存储),我的身份验证将失败且没有任何有意义的错误。
您是否在使用主机重写?延迟对我来说非常重要,但如果我不使用托管重写,它就会完全消失。
【参考方案1】:
它有时为 null 有时不为 null 的事实可能表明存在异步问题。您是否在上面的 if 语句中进行检查?所有对用户的引用都应该在回调中。如果一切顺利,则可能检查身份验证是否已正确启动。
【讨论】:
感谢您的评论。是的,我确定用户 obj 仅在onAuthStateChanged
方法中被引用。【参考方案2】:
你没有打电话给onAuthStateChanged
。相反,您是在告诉 Firebase 在身份验证状态更改时调用 您,这可能会在重新加载页面时发生几次
当页面正在加载并且之前有用户登录时,身份验证状态可能会更改几次,而客户端正在确定用户的身份验证状态是否仍然有效。因此,您可能在看到实际登录用户的最终通话之前看到没有用户的通话。
【讨论】:
感谢您的建议。就我而言,无论用户是否登录,firebase 都不能保证在重新加载页面时调用 onAuthStateChanged ......我的理解是否正确?如果是这样,我是否应该在清楚地完成重新加载后调用其他方法,如auth.currentUser
?
您的onAuthStateChanged
回调将在页面加载时以当前状态调用,然后在每个阶段更改时调用。这正是它的目的。如果您更新您的问题以包含minimal complete reproduction of the problem,那么提供更多帮助会更容易,因为现在我只能说听起来事情正在按预期工作。
我已根据您的建议更新了我的问题。如果您检查我的更新,我将不胜感激。
...我实际上只是测试了 w console.log
并且 firebase.auth() 最初并没有像以前那样使用 null
触发。它仍然异步触发,我的 UI 仍然闪烁。 ...proly 我的编码应该更新以静音闪烁(例如登录按钮display:none
vs photoURL <img>
acct menu)...
嗯,我觉得我的应用程序的行为很有趣(或奇怪)。我的理解是:除非用户删除他的身份验证状态或本地存储,否则不会返回 Null。最后,我发现删除我的 chrome 上的任何缓存,然后问题暂时不会出现,但是,有时这种情况仍然可能发生。因此,如果身份验证失败,我决定删除会话并将重定向设置为登录页面。你的建议对我帮助很大。谢谢!【参考方案3】:
onAuthStateChanged 是 firebase 文档中所述的观察者,当身份验证状态发生变化时触发,例如用户登录、退出、密码更改。要检查用户是否登录,您应该使用 firebase.auth().currentUser 这将为您提供当前登录的用户。正如您所说,您的状态是本地 firebase.auth().currentUser 将始终为您提供用户,除非用户退出。
【讨论】:
以上是关于有时 firebase.auth().onAuthStateChanged 在我刷新页面时返回 null 用户的主要内容,如果未能解决你的问题,请参考以下文章
致命错误:找不到模块“firebase_auth”@import firebase_auth
GeneratedPluginConstraint,致命错误:找不到模块“firebase_auth”@import firebase_auth;
firebase.auth().currentUser 为空
如何在 firebase-functions 中使用 firebase.auth()?
错误:名称“用户”在库“package:firebase_auth/firebase_auth.dart”和“package:quizmaker/models/user.dart”中定义