Ionic+Angular项目Firebase用户登出提示权限不足如何解决
错误根本原因
触发登出后,afAuth.signOut() 会先清除当前用户的登录态,但你之前在auth.service.ts里给user$流配置的switchMap返回的Firestore文档valueChanges()是持久化订阅,登录态消失后,这个还未取消的订阅仍会尝试请求Firestore资源。你的Firebase安全规则大概率限制了只有用户本人才能读自己的user文档,未登录状态没有访问权限,就会抛出权限不足的错误。
可行解决方案
方案1:登出前主动取消页面侧的订阅
你已经在app.component.ts中将订阅赋值给了this.appSub,只要在触发登出前先取消该订阅即可:
// app.component.ts 修改onLogout方法 //Logout Button onLogout(){ // 先取消Firestore文档的订阅,再执行登出 this.appSub?.unsubscribe(); this.authService.signOut(); }
方案2:给数据流添加自动销毁逻辑
在auth.service.ts内添加登出触发器,登出时自动停止所有Firestore监听,从数据流底层避免权限请求,适配多页面订阅用户数据的场景:
首先导入需要的rxjs依赖:
import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators';
修改service内部逻辑:
// auth.service.ts 新增私有属性 private unsubscribe$ = new Subject<void>(); // 修改user$的流配置 constructor( private afs: AngularFirestore, private afAuth: AngularFireAuth, private router: Router ) { this.user$ = this.afAuth.authState .pipe( switchMap( user => { if (user) { return this.afs.doc<User>(`user/${user.uid}`).valueChanges() .pipe(takeUntil(this.unsubscribe$)); // 登出时自动终止该订阅 } else { return of(null); } }) ) } // 修改signOut登出方法 async signOut(){ // 先触发所有关联订阅的终止信号 this.unsubscribe$.next(); this.unsubscribe$.complete(); const loading = await this.loadingCtrl.create({ spinner: 'crescent', showBackdrop: true }); loading.present(); this.afAuth.signOut() .then(() => { loading.dismiss(); this.router.navigate(['/login']); }).catch(error => { console.log(error.message); }); }
方案3:补充错误捕获逻辑(辅助方案)
如果不想改动现有订阅逻辑,可以在用户数据订阅处添加错误捕获,直接忽略登出触发的权限错误:
// app.component.ts 修改订阅逻辑 this.appSub = this.authService.user$.subscribe({ next: async user => { this.user = user; if(user) { this.userId = user.userId; try { this.userPhoto = user.userPhoto; } catch (error) { console.log('No User Photo'); } } }, error: (err) => { // 仅过滤登出触发的权限错误,其余错误仍正常抛出 if(err.toString().includes('Missing or insufficient permissions')) { console.log('用户已登出,停止监听用户数据'); } else { console.error(err); } } });
内容的提问来源于stack exchange,提问作者John Paulo A. Geronimo
相关产品推荐
相关产品推荐

