Firebase 安全规则:限制仅写入此 uid,几个字段除外

Posted

技术标签:

【中文标题】Firebase 安全规则:限制仅写入此 uid,几个字段除外【英文标题】:Firebase security rules: restrict write only to this uid, except for a couple of fields 【发布时间】:2017-10-15 09:49:25 【问题描述】:

在 Firebase 中,我有一个 users“节点”,它看起来像:

users: 
  someUid: 
    username: 'someUsername'
    activeConversations: ,
    profile_picture: ''
    ... lots of other children
  ,
  ...
,
anotherNode: 

,
... hundreds of other nodes

我现在的规则:


  "rules": 
    ".read": true,
    ".write": true,
    "users": 
      ".indexOn": [
        "username"
      ]
    ,
    "friendRequests": 
      ".indexOn": [
        "timeSent"
      ]
    
  

我想要做的是将users“节点”中的孩子的访问权限仅限于拥有孩子的客户。因此,例如,someUid 子级只能由具有 uid someUid 的客户端写入。 anotherNode 等其他“节点”可以被任何登录的客户端写入/读取。 此外,任何已登录的客户端都应该能够在users 文档中的profile_pictureactiveConversations 上进行书写。

如何在不必在每个节点上都设置读/写规则的情况下实现这一点?

谢谢

【问题讨论】:

【参考方案1】:

根据 firebase 文档,您可以在用户级别和数据级别限制访问权限

例如,

    // These rules grant access to a node matching the authenticated
    // user's ID from the Firebase auth token
    
      "rules": 
        "users": 
          "$uid": 
            ".read": "$uid === auth.uid",
            ".write": "$uid === auth.uid"
          
        
      
    

你也可以在数据级别限制读写权限,


  "rules": 
    "messages": 
      "$message": 
        // only messages from the last ten minutes can be read
        ".read": "data.child('timestamp').val() > (now - 600000)",

        // new messages must have a string content and a number timestamp
        ".validate": "newData.hasChildren(['content', 'timestamp']) && newData.child('content').isString() && newData.child('timestamp').isNumber()"
      
    
  

浏览这些 firebase 官方文档, https://firebase.google.com/docs/database/security/quickstart https://firebase.google.com/docs/database/security/user-security https://firebase.google.com/docs/database/security/securing-data

【讨论】:

【参考方案2】:

我认为@Bradley Mackey 差不多了,但只需要稍作调整。


  "rules": 
    "users": 
      ".indexOn": ["username"],
      // wildcard, matches any node under 'users'
      "$someUid": 
        "$other" : 
          ".read": "($other == 'profile_picture' || $other == 'activeConversations') || auth.uid == $someUid", 
          ".write": "($other == 'profile_picture' || $other == 'activeConversations') || auth.uid == $someUid", 
        
      
    ,
    "$anythingelse": 
      ".read": "auth != null",
      ".write": "auth != null",
    
  

".validate": 字段确保字段匹配特定格式。如果字段是 profile_picture 或 activeConversations,这里的读写应该给每个人读写权限,并给用户对其他所有内容的访问权限。

编辑:

我添加了另一个规则,允许任何登录用户对任何非用户节点进行读写访问。

【讨论】:

嗨,亚当。谢谢。但是,users 旁边的其他节点呢?默认情况下,如果未设置,则没有读/写访问权限。 users 同一级别的其他节点应该具有读/写访问权限。 现在编辑希望能做你想做的事。 好答案。 "$anythingelse"之前需要一个逗号 谢谢鲍勃,在 我试过了,它不起作用,我不确定现在的陷阱在哪里,我正在调查它是否来自我自己的数据,例如profile_picture以外的字段和activeConversations 需要写/读访问权限。一旦我深入研究它就会回到这里。【参考方案3】:

".read": true, ".write": true 放在数据库的根目录是一个非常糟糕的想法。从字面上看,任何人都可以随时擦除整个数据库或插入任何数据。这是因为 .read.write 规则级联,所以如果您让它们在某个节点上评估为 true,则此人也有权该节点的所有子节点。

幸运的是,更安全的规则(例如您提出的规则)很容易实施。我假设someUid 等于用户auth.uid 你可以这样做:


  "rules": 
    "users": 
      ".indexOn": ["username"],
      // wildcard, matches any node under 'users'
      "$someUid": 
        ".read": "auth != null",
        ".write":"auth != null",
        "$other" : 
          ".validate": "($other == 'profile_picture' || $other == 'activeConversations') || auth.uid == $someUid" // only that own user can change their username
        
      
    
  

我已经省略了您的 friendRequests 节点,因为我不确定您需要什么样的安全规则,但我希望这足以让您入门。

Firebase docs 很好地涵盖了这些内容。

【讨论】:

感谢布拉德利。如何保持对activeConversationsprofile_picture 的任何经过身份验证的用户的写访问权限? 对于friendRequests等节点,我们可以保留write: trueread: true。如果我们把它放在全局范围内,它会为所有节点级联(例如在users 中设置它时,它会覆盖那些)? @DanP。请参阅我更新的答案,也不要将它们设置为true,除非您非常明确地需要它。这是非常糟糕的做法,至少检查auth != null 谢谢。除了用户名、profile_picture 等,我实际上还有 50 个孩子。是否可以将默认设置为auth != null && auth.uid == $someUid,并将profile_pictureactiveConversations 设置为auth != null? (基本上把username下写的规则换成$other下的规则) @DanP。是的,你可以轻松做到!

以上是关于Firebase 安全规则:限制仅写入此 uid,几个字段除外的主要内容,如果未能解决你的问题,请参考以下文章

安全规则中的 Firebase 速率限制?

Firebase安全规则,在不同位置具有读写功能

Firebase 实时电话数据库安全规则

Firebase 存储安全规则

Cloud Firestore 安全规则只允许从 Firebase 函数写入

Firebase/数据库 - 第 2 版安全规则?