【问题标题】:"Insufficient permissions" error when signing out of Firebase React app退出 Firebase React 应用时出现“权限不足”错误
【发布时间】:2020-09-23 01:10:17
【问题描述】:

我的项目在 React/Firebase 中。我收到“onSnapshot 中未捕获的错误:FirebaseError:缺少权限或权限不足”。注销时。有读/写规则,所以我得到错误是有道理的。

我认为这与onSnapshot 听众如何分离有关,根据: Firebase rules when user log out 'Missing or insufficient permissions. Error: Missing or insufficient permissions'

我不确定我在分离它们时做错了什么 - 项目中有 6 个快照侦听器,并且(我认为)我已将其缩小到以下组件提供用户信息:

const UserProvider = props => {
  const [{ user }, setUser] = useState({ user: null });
  const unsubscribeRef = useRef(null);

  useEffect(() => {
    auth.onAuthStateChanged(async user => {
      if (user) {
        const userRef = await createUserProfileDocument(user);

        unsubscribeRef.current = userRef.onSnapshot(snapshot => {
          setUser({ user: { uid: snapshot.id, ...snapshot.data() } });
        });
      }
    });

    return () => unsubscribeRef.current();
  }, []);

  return (
    <UserContext.Provider value={user}>{props.children}</UserContext.Provider>
  );
};

之前,我只是将 unsubscribe 变量直接附加到 userRef.onSnapshot 位,但没有运气——这就是我在这里尝试 useRef 的原因。我想知道是否需要以某种方式附加调用 signOut 的点?似乎没有其他 React/Firebase 应用程序示例使用它。最后,我不明白为什么,但 useEffect 中的 return 语句似乎永远无法到达这里。

如果有帮助,这是Authentication 组件:

const Authentication = () => {
  const history = useHistory();

  useEffect(() => {
    auth.onAuthStateChanged(async userAuth => {
      if (userAuth) {
        if (history.location.pathname === ROUTES.SIGN_IN)
          history.push(ROUTES.HOME);
      } else {
        history.push(ROUTES.SIGN_IN);
      }
    });
  }, [history]);

  return null;
};

编辑: 这些是 Firestore 中的规则:

match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if getUserData().admin == true;
    }

    function getUserData() {
      return get(/databases/$(database)/documents/users/$(request.auth.uid)).data
    }
  }

我不确定这里还有什么相关的。退出后,用户将被路由回登录页面,该页面不使用数据库中的任何内容。

App() 的结构如下:

function App() {
  return (
    <UserProvider>
      <Router>
        <Authentication />
        <Switch>
          <Route path="/signin" component={SignIn} />
          <Route path="/forgot" component={ForgotPasswordView} />

          <CatalogProvider>
            <Route path="/" component={Main} />
          </CatalogProvider>
        </Switch>
      </Router>
    </UserProvider>
  );
}

Main 包含应用程序的其余工作部分。

【问题讨论】:

  • 请编辑问题以显示所有相关代码,尤其是因您显示的错误而失败的数据库查询。由于这是一个权限错误,因此还要显示拒绝查询的安全规则。我们需要能够将 specific 查询与 specific 规则相匹配。
  • @DougStevenson 我已经更新了我的问题,希望它足够...

标签: javascript reactjs firebase firebase-authentication


【解决方案1】:

需要意识到的是,onAuthStateChanged 将在用户退出时为您提供一个空用户对象。您的代码似乎无法处理这种情况。

另外需要意识到的是,当用户退出时,如果查询上的任何活动监听器由于安全规则而变得无效(例如,request.auth 变为空),那么监听器将被切断并获得权限错误。您应该在在退出之前删除依赖于身份验证的查询的所有持久侦听器,或者只是接受错误将会发生并自动删除侦听器。

【讨论】:

  • 谢谢,这很有帮助。你对处理onAuthStateChanged返回的空用户对象有什么建议吗?
  • 至少检查一下,什么都不做,如果那是你想要的?您决定用户退出时会发生什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-10
  • 1970-01-01
  • 2015-04-11
  • 2012-11-08
  • 2021-10-31
相关资源
最近更新 更多