当前位置: 首页 > 知识库问答 >
问题:

Firebase实时数据分片规则

阙阳夏
2023-03-14

更新2019-11-03:添加了错误的实时最小复制。在Chrome中加载链接后,点击ctrl shift i并选择控制台以查看输出。我已经尽力确保这正是我最初的项目代码所做的;我们看看情况是否如此,嗯?碎片的规则文件与下面的原始帖子相同。该源代码可在GitHub上获得。

<!DOCTYPE html>
<html>
<body>
 <script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-app.js"></script>
 <script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-auth.js"></script>
 <script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-database.js"></script>
 <script>
  const config={
   apiKey: "AIzaSyDLMc0GUf5n2nQa3aqpELQu7lziprQOGs8",
   authDomain: "shardautherror.firebaseapp.com",
   databaseURL: "https://shardautherror.firebaseio.com",
   projectId: "shardautherror",
   storageBucket: "shardautherror.appspot.com",
   messagingSenderId: "841096336504",
   appId: "1:841096336504:web:9899961c8250caa552498d"
  };

  const shard="https://shardautherror-1e9ed.firebaseio.com/";

  async function init(){
   try{
    firebase.database.enableLogging(true);
    const defaultApp=firebase.initializeApp(config);
    const auth=defaultApp.auth();
    const s="alice@example.com";
    await auth.signInWithEmailAndPassword(s,s);
    const uid= auth.currentUser.uid;
    const shardApp=firebase.initializeApp({databaseURL:shard},'dbAppShard');
    const db=firebase.database(shardApp);
    const ref= db.ref("/chat/"+uid+"/fail/"+uid);
    const time= firebase.database.ServerValue.TIMESTAMP;
    ref.set({time});
   } catch(e) {
    console.error("init failed",e);
   }
  }

  init();
 </script>
</body>
</html>

原文:

这些规则在模拟器中工作,但在我真正的网络应用程序中不工作。模拟器路径和有效负载与下面数据库日志输出中显示的相同。

数据库。规则。jsonmain将两个碎片作为目标,以使用此规则文件;我在部署时进行了验证)

{
 "rules":{
  "chat":{
   "$ownerId":{
    "fail":{
     "$pId":{
      ".write": "$pId== auth.uid&& $ownerId== auth.uid",
      "time":{".validate": "newData.val()== now"},
      "$other":{".validate": "newData.isString()&& newData.val().length>= 28"}
     }
    }
   }
  }
 }
}

失败的set命令的Firebase日志记录输出。它只写一个名为time的值。这是我第一次尝试使用rtdb。我已经安排好了切丁。它在试图访问实时数据库之前就从firestore获取了碎片名称,但它看起来不像是竞争条件(尽管有日志记录输出),原因我将在下面概述。

index.esm.js:81 [2019-10-19T03:02:53.281Z]  @firebase/database: 0: set 
 {"path":"/chat/rpNIK41hNpWkYY2KqndkwCzPJuF3/fail/rpNIK41hNpWkYY2KqndkwCzPJuF3",
  "value":{"time":{".sv":"timestamp"}},"priority":null} 
22:02:53.285 index.esm.js:81 [2019-10-19T03:02:53.285Z]  @firebase/database:
 p:0: Buffering put: /chat/rpNIK41hNpWkYY2KqndkwCzPJuF3/fail/rpNIK41hNpWkYY2KqndkwCzPJuF3 
22:02:53.293 index.esm.js:81 [2019-10-19T03:02:53.293Z]  @firebase/database:
 p:0: Making a connection attempt 
22:02:53.294 index.esm.js:81 [2019-10-19T03:02:53.294Z]  @firebase/database:
 getToken() completed. Creating connection. 
22:02:53.295 index.esm.js:81 [2019-10-19T03:02:53.295Z]  @firebase/database:
 c:0:0: Connection created 
22:02:53.296 index.esm.js:81 [2019-10-19T03:02:53.296Z]  @firebase/database:
 p:0: Auth token refreshed 
22:02:53.298 index.esm.js:81 [2019-10-19T03:02:53.298Z]  @firebase/database:
 c:0:0:0 Websocket connecting to wss://quickstart-1551998385825-7f7a6.firebaseio.com/.ws?v=5 
22:02:53.534 index.esm.js:81 [2019-10-19T03:02:53.534Z]  @firebase/database:
 c:0:0:0 Websocket connected. 
22:02:53.539 index.esm.js:81 [2019-10-19T03:02:53.539Z]  @firebase/database:
 c:0:0: Realtime connection established. 
22:02:53.539 index.esm.js:81 [2019-10-19T03:02:53.539Z]  @firebase/database:
 p:0: connection ready 
22:02:53.542 index.esm.js:81 [2019-10-19T03:02:53.541Z]  @firebase/database:
 p:0: reportStats {"c":{"sdk.js.7-0-0":1}} 
22:02:53.542 index.esm.js:81 [2019-10-19T03:02:53.542Z]  @firebase/database:
 p:0: {"r":1,"a":"s","b":{"c":{"sdk.js.7-0-0":1}}} 
22:02:53.546 index.esm.js:81 [2019-10-19T03:02:53.546Z]  @firebase/database:
 p:0: {"r":2,"a":"p","b":{"p":"/chat/rpNIK41hNpWkYY2KqndkwCzPJuF3/fail/rpNIK41hNpWkYY2KqndkwCzPJuF3",
  "d":{"time":{".sv":"timestamp"}}}} 
22:02:53.591 index.esm.js:81 [2019-10-19T03:02:53.591Z]  @firebase/database:
 p:0: from server: {"r":1,"b":{"s":"ok","d":""}} 
22:02:53.595 index.esm.js:81 [2019-10-19T03:02:53.595Z]  @firebase/database:
 c:0:0: Primary connection is healthy. 
22:02:53.596 index.esm.js:81 [2019-10-19T03:02:53.596Z]  @firebase/database:
 p:0: from server: {"r":2,"b":{"s":"permission_denied","d":"Permission denied"}} 
22:02:53.597 index.esm.js:81 [2019-10-19T03:02:53.597Z]  @firebase/database:
 p:0: p response {"s":"permission_denied","d":"Permission denied"} 

因此,在此之后,如果我将规则更新为“.write”:true,则时间戳的写入成功。在日志中显示“r”:3 ,所以我知道它没有放弃连接并重新启动。如果我随后将其更改为。.write:“auth.uid!=null”、。.write:“auth!=null”、(因此,不检查所有权,只检查客户端是否登录,与上面不同),它会再次使用“r”拒绝权限:4。。。“指示第四个请求。因此,客户端似乎完全无法向碎片进行身份验证。

建议?我肯定我做错了什么。

顺便说一下,用户留档到处都是...这些都有效吗?

"baskets": {
  ".read": "auth.uid != null &&// auth.uid!= null from https://firebase.google.com/docs/database/security/securing-data
".read": "auth != null && auth.uid == $uid" // auth != null from https://firebase.google.com/docs/database/security/user-security
".write": "$user_id === auth.uid" // triple equal from https://firebase.google.com/docs/database/security/user-security
 ".write": "request.auth.uid == uid" // request.auth from realtime database tab of content owner access from https://firebase.google.com/docs/rules/basics

共有2个答案

曹旭东
2023-03-14

这条线

const shardApp=firebase.initializeApp({databaseURL:shard},'dbAppShard');

需要更改为:

const shardApp=firebase.initializeApp({...config,databaseURL:shard},'dbAppShard');

如果客户端最近已经登录到ShardApp的auth()对象,这将起作用。如果没有,它可以通过以下函数来完成:ShardApp.auth(). SignInBackEmail AndPassword(email, pw)ShardApp.auth(). updateMONtUser(user),其中user可以来自例如默认应用程序auth()。当前用户对象。或者,目前仍然可以只使用默认应用程序,然后调用defaultApp.database(ShardURL),但在撰写本文时,我不知道这种方法是否会保留在Firebase中。

当前的firebase分片文档仅显示客户端仅将数据库URL参数传递给initializeApp,这不足以使用基于身份验证的规则。与此管理函数answer和此旧语法多数据库切分介绍博客帖子不同,当前文档要求客户端构造和管理多个应用程序对象。正如Firebase支持人员和我发现的那样,非默认应用程序当前不会从默认应用程序对象(即第一个应用程序,创建时没有第二个参数initializeApp)中提取API密钥和其他参数。

Firebase支持已经回答了我提出的有关规则的附带问题:

  • A) RTDB使用auth,而Firestore使用请求。验证

注意A)表示文档中的这个示例是错误的,因为它使用了请求。RTDB中的身份验证

{
  "rules": {
    "some_path": {
      "$uid": {
        // Allow only authenticated content owners access to their data
        ".read": "request.auth.uid == uid"
        ".write": "request.auth.uid == uid"
      }
    }
  }
}
通建安
2023-03-14

这里有两个问题,问题的第一部分需要更多信息。

问题的第二部分

顺便说一下,用户留档到处都是...这些都有效吗?

留档并不是到处都是。您包含的每个规则示例都来自不同的用例。

例如,“篮子”中的. read规则适用于特定节点“篮子”,确保只有经过身份验证的用户才能读取篮子节点。它将允许任何授权用户读取该节点。还有一个额外的

第二个读取规则将应用于它所在的任何节点,并将确保用户经过身份验证,并且只有经过身份验证的用户才能读取该节点(即,它是他们的节点,其他人无法访问)

对于写入的===(三等)被覆盖在留档中,并表示

不e:: ==处理为===。如果您在安全规则中使用==,当规则运行时,它将被转换为===。

最后一次写入只是检查请求的uid是否是当前已验证的用户。

 类似资料:
  • 我尝试用规则返回用户聊天列表。所以我不知道对话的id。我尝试了几种方法,但都不起作用,因为你必须知道聊天id。 数据库: 规则: 但当我从react本机应用程序访问时。通过身份验证的用户无法访问聊天记录(uid:3Oi1atf8l2P4Vgsb8tZOGxpUg7q2) *读取失败:错误:权限被拒绝/Chats:客户端没有访问所需数据的权限。 规则: 查询:

  • 我使用以下规则检查只有“管理员”才能写入陷阱部分。 这个很好用。但是如果我把规则改为, 然后我得到了一个权限错误。W/SyncTree:侦听/traps失败:数据库错误:权限被拒绝。 我之所以改变结构,是因为我试图使用validate函数,但由于我无法通过第一个问题,我无法达到验证的程度。 我肯定这是一个新手理解错误,但在尝试了许多排列后,我在这方面进展甚微。您的协助将不胜感激。 更新201606

  • 我有一个数据库: 当用户()在应用程序中注册时,他会填充另一个用户uid(该用户uid具有属性)并将自己的uid添加到他的个人资料中(

  • 如果我在公共模式下使用Firebase实时数据库发布我的Android应用程序会怎么样,因为我不需要任何身份验证。它说 公共访问使您的数据库对任何人开放,即使是不使用您的应用的人,因此请务必在设置身份验证时再次限制您的数据库。 我不清楚,如果他们的应用程序没有连接到我的数据库,而且他们也没有firebase帐户的登录密码,那么他们怎么能访问我的数据库。 提前发送Thx

  • 我有一个关于firebase实时数据库规则的问题。 有人创建了一个帐户,该帐户在实时数据库中创建了一个路径: 结构很简单(密钥、用户ID和其他数据)。 这是我的规则: 但现在问题来了。如何允许用户写入此对象?每个拥有代码的人(请参阅BQUyhq)w3D)都可以写入对象id。如果没有代码,他们就无法写入对象id。 有可能发生这样的事吗?如果是的话,我该怎么做呢。

  • 我正在尝试为我的Firebase实时数据库设置规则,但我不明白为什么它们不起作用。下面是数据顶部的样子: 假设我希望允许用户读取其用户名与数据中的name字段匹配的数据。我以为这样的事情会奏效 不幸的是,这对我不起作用。为了学习,我甚至试过这个 或者甚至 这到底是怎么回事