在 Angular PWA 中,我使用 firebase 安全规则将对几乎所有数据的访问限制为经过身份验证的用户。在 auth-guard 中,我检查用户是否经过身份验证,如果没有,则用户匿名登录 (
signInAnonymously()
) 所以我确保我有一个用户 ID,我可以用它来标记用户创建的对象。这个标志是必要的,所以我知道用户是否是创建者以及他是否被允许删除自己的评论。
一切正常 - 当我失去连接时也是如此。但是,如果我关闭 PWA,启用飞行模式,然后打开 PWA(无连接)——
signInAnonymously
返回错误(当然是因为用户无法在服务器上登录)。另一方面,我希望要么让用户从 LocalStorage / IndexedDb
返回,要么在打开应用程序后,onAuthStateChanged
-Event 与本地存储的用户一起触发。
这一切都没有发生(尽管我看到,用户实际上被 Firebase 存储在 indexeddb 中)。 文档:身份验证状态持久性 还指出,
对于 Web 应用程序,默认行为是即使在用户关闭浏览器后仍保留用户的会话。
我错过了什么?我应该做些什么来实现我的目标:
PWA 应该像原生应用一样运行。如果我没有连接,因为我使用 Firestore
,应用程序应该加载缓存中的任何数据,一旦连接恢复,应用程序应该无缝地使用在线数据。enableIndexedDbPersistence()
编辑: 这是我
AuthService
的代码。不幸的是,在飞行模式下,来自 onAuthStateChanged
的用户始终为空(当我有连接时它不是):
@Injectable()
export class AuthService {
private authState: User = null;
public get isAuthenticated() {
return this.authState !== null;
}
constructor(private fAuth: Auth) {
onAuthStateChanged(this.fAuth, async (user) => {
// For Debug-Purposes
document.body.prepend('oac: ' + JSON.stringify(user));
this.authState = user;
try {
if (!this.isAuthenticated) {
this.authState = (await signInAnonymously(this.fAuth)).user;
}
} catch (e) {
console.error(e);
}
});
}
}
听起来您的代码总是在页面加载时调用
signInAnonymously
,以匿名登录用户。这实际上是一种反模式,因为这意味着 SDK 将调用服务器,这解释了为什么您的代码失败。
恢复用户登录状态的惯用方法是使用
onAuthStateChange
侦听器,如getting the current user文档中的第一个代码示例所示:
import { getAuth, onAuthStateChanged } from "firebase/auth";
const auth = getAuth();
onAuthStateChanged(auth, (user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
const uid = user.uid;
// ...
} else {
// User is signed out
// ...
}
});
然后只有当没有当前用户时,您才会调用
signInAnonymously
(或任何其他登录提供商)进行首次登录。