【问题标题】:Uncaught Error in onSnapshot: Error: Missing or insufficient permissions on signOut()onSnapshot 中未捕获的错误:错误:signOut() 权限缺失或权限不足
【发布时间】:2019-05-04 05:22:17
【问题描述】:

我正在使用vuex和firebase按照vuegram的说明实现用户认证。我尝试了很多方法来分离 firebase 监听器,唯一停止警告错误的方法如下:

var unsubscribe=fb.auth.onAuthStateChanged(user=>{
    if(user){
        store.commit('setCurrentUser',user)
        store.dispatch('fetchUserProfile')

        fb.usersCollection.doc(user.uid).onSnapshot(doc => {
            store.commit('setUserProfile', doc.data())
        })
    }
})
unsubscribe();

但是,上面的代码只是停止了 signOut() 上的警告,我不能再更新数据了。

我的 store.js 文件:

var unsubscribe=fb.auth.onAuthStateChanged(user=>{
    if(user){
        store.commit('setCurrentUser',user)
        store.dispatch('fetchUserProfile')

        fb.usersCollection.doc(user.uid).onSnapshot(doc => {
            store.commit('setUserProfile', doc.data())
        })
    }
})

export const store=new Vuex.Store({
    state:{
        currentUser:null,
        userProfile:{}
    },
    actions:{
        clearData({commit}){
            commit('setCurrentUser',null)
            commit('setUserProfile', {})
        },
        fetchUserProfile({ commit, state }) {
             fb.usersCollection.doc(state.currentUser.uid).get().then(res => {
                commit('setUserProfile', res.data())

            }).catch(err => {
                console.log(err)
            })
        },
        updateProfile({ commit, state }, data) {
            let displayName = data.displayName

            fb.usersCollection.doc(state.currentUser.uid).set({
                displayName: displayName
            }, {merge:true}).then(function() {
                alert("Document successfully written!");
            })
            .catch(function(error) {
                alert("Error writing document: ", error);
            });
        }
    },
    mutations:{
        setCurrentUser(state, val) {
            state.currentUser = val
        },
        setUserProfile(state, val) {
            state.userProfile = val
        }
    }
})

signOut 方法:

signOut: function(){
        fb.auth.signOut().then(()=> {
            this.$store.dispatch('clearData')
            this.$router.push('login')
        }).catch(function(error) {
            console.log(error);
        });
    }

我的 Firebase 规则:

allow read, write: if request.auth.uid!=null;

【问题讨论】:

  • 因为你还在订阅数据。首先取消订阅然后调用注销:)
  • 我应该在哪里调用 unsubscribe()?如果我在 clearData() 中调用它,它是未定义的

标签: firebase google-cloud-firestore vuex


【解决方案1】:

由于您在注销时仍然有一个活动的侦听器,因此系统会检测到客户端已失去读取该数据的权限并拒绝该侦听器。这意味着您需要在退出前移除侦听器以防止出现错误消息。

参见documentation on detaching listeners,你在附加监听器时首先得到一个对取消订阅函数的引用:

unsubscribe = fb.usersCollection.doc(user.uid).onSnapshot(doc => {
    store.commit('setUserProfile', doc.data())
})

然后在退出前调用该函数:

signOut: function(){
    unsubscribe();
    fb.auth.signOut().then(()=> {
        this.$store.dispatch('clearData')
        this.$router.push('login')
    }).catch(function(error) {
        console.log(error);
    });
}

【讨论】:

  • 仍然给我错误。是否有必要捕获此错误?为什么 signOut 方法不会自动为我们分离监听器?
  • 有很多用例,当用户退出时,监听器可以保持活动状态。但是在您的情况下,侦听器被删除,它只是明确告诉您它已被取消,因为这可能是一个问题。如果这是您想要的结果,您可以根据需要忽略该错误。但是,如果您仍然收到错误,那么您仍然有一个需要经过身份验证的用户的侦听器,我个人强烈希望知道我的代码在这种情况下正在做什么。
  • 谢谢泡芙,我只是用get()的方法获取数据,而不是onSnapshot(),报错就没有了。
  • 在退出前必须删除监听器是荒谬的。它应该在退出时是隐式的,一旦 firestore 实例知道您需要签署哪些并且没有可能未经许可访问其中之一。注销应该只是自动取消订阅所有这些,因此您必须跟踪每个快照事件......现在想象一下像我这样的大型应用程序。没有意义
  • 当侦听器失去对基础数据的访问权限时,它会自动取消。为确保您知道发生这种情况,这会为已取消的侦听器引发错误事件。
【解决方案2】:

如果您在许多页面上都有注销按钮,只需导航到不同的页面并从那里调用注销。这样您就不必在取消订阅时乱扔代码了。

【讨论】:

    【解决方案3】:

    您也可以查看您的Firestore rules

    如果是这样的话:

    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /{document=**} {
          allow read, write: if false;
        }
      }
    }
    

    改为:

    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /{document=**} {
          allow read, write: if true;
        }
      }
    }
    

    请注意,这是不安全的,仅用于开发目的。要了解 Firestore 规则的工作原理,请查看 this youtube video

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-12
      • 2019-01-29
      • 2018-08-24
      • 1970-01-01
      • 2018-08-30
      • 1970-01-01
      • 1970-01-01
      • 2021-03-10
      相关资源
      最近更新 更多