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_picture
和activeConversations
上进行书写。
如何在不必在每个节点上都设置读/写规则的情况下实现这一点?
谢谢
【问题讨论】:
【参考方案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 很好地涵盖了这些内容。
【讨论】:
感谢布拉德利。如何保持对activeConversations
和profile_picture
的任何经过身份验证的用户的写访问权限?
对于friendRequests
等节点,我们可以保留write: true
和read: true
。如果我们把它放在全局范围内,它会为所有节点级联(例如在users
中设置它时,它会覆盖那些)?
@DanP。请参阅我更新的答案,也不要将它们设置为true
,除非您非常明确地需要它。这是非常糟糕的做法,至少检查auth != null
。
谢谢。除了用户名、profile_picture 等,我实际上还有 50 个孩子。是否可以将默认设置为auth != null && auth.uid == $someUid
,并将profile_picture
和activeConversations
设置为auth != null
? (基本上把username
下写的规则换成$other
下的规则)
@DanP。是的,你可以轻松做到!以上是关于Firebase 安全规则:限制仅写入此 uid,几个字段除外的主要内容,如果未能解决你的问题,请参考以下文章