AngularFire登录提示Missing or insufficient permissions,刷新后正常如何解决
问题根因
你的猜测是正确的,核心问题是登录逻辑混用了Firebase原生Web SDK API和AngularFire封装的服务实例,导致登录状态不同步:
- AuthService的
login方法中调用getAuth()获取的是原生Firebase Auth实例,和注入的angularFireAuth属于两个独立的实例,原生API登录成功后,不会同步触发angularFireAuth.authState的状态更新。 - 登录成功跳转首页时,
angularFireAuth.authState还未接收到有效的登录态,此时发起的Firestore请求没有携带用户凭证,直接触发权限不足报错。 - 页面刷新后AngularFire会重新初始化,同步读取本地存储的登录凭证,请求恢复正常。登出后直接重新登录的场景同理,旧的AngularFire状态缓存和原生登录态没有同步。
- 额外问题:RepositoryService中每次
authState变化时都会新建valueChanges订阅,旧的订阅没有被销毁,登出状态下残留的无效订阅也会触发权限报错。
解决方案
1. 统一登录API,避免混用原生和AngularFire实例
修改AuthService的登录逻辑,统一使用注入的angularFireAuth提供的方法:
@Injectable({ providedIn: "root" }) export class AuthService { constructor(private angularFireAuth: AngularFireAuth, private router: Router) { } public login() { this.angularFireAuth.signInWithPopup(new GithubAuthProvider()) .then(() => { this.router.navigate(["/"]); }) .catch((error) => { console.log(error); }); } // 登出也统一使用angularFireAuth的API public logout() { this.angularFireAuth.signOut(); } }
2. 优化Firestore订阅逻辑,避免残留无效请求
使用switchMap自动切换订阅,取消上一次的无效请求,同时也可以避免内存泄漏:
import { switchMap } from 'rxjs/operators'; import { of } from 'rxjs'; @Injectable({ providedIn: "root" }) export class RepositoryService { // 直接返回Observable,不需要手动维护BehaviorSubject repositories$: Observable<Repository[]> = this.angularFireAuth.authState.pipe( switchMap(authUser => { if (authUser) { return this.firestore .collection("user") .doc(authUser.uid) .collection<Repository>("repositories") .valueChanges(); } // 未登录时返回空数组 return of([]); }) ); constructor(private angularFireAuth: AngularFireAuth, private firestore: AngularFirestore) {} }
如果业务需要保留BehaviorSubject,也可以在每次新建订阅前,先取消上一次的valueChanges订阅即可。
修改完成后,无论是首次登录还是登出后直接重新登录,登录状态都会同步更新,Firestore请求会携带正确的用户凭证,不会再触发权限不足报错。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

