Firebase 使用安全规则限制子/字段访问
我正在编写一个应用程序,允许用户提交提名,提名在显示给其他用户之前经过审核。这需要一些限制,我迄今为止在安全规则方面没有成功实施:Firebase 使用安全规则限制子/字段访问,firebase,firebase-realtime-database,Firebase,Firebase Realtime Database,我正在编写一个应用程序,允许用户提交提名,提名在显示给其他用户之前经过审核。这需要一些限制,我迄今为止在安全规则方面没有成功实施: 隐藏任何尚未批准的提名 对提交隐藏私人字段(电话、批准状态、创建日期等) 我目前的规则如下: { "rules": { "nominations": { ".read": true, "$nominationId": { ".read": "data.child
{
"rules": {
"nominations": {
".read": true,
"$nominationId": {
".read": "data.child('state').val() == 'approved' || auth != null", // Only read approved nominations if not authenticated
".write": "!data.exists()", // Only allow new nominations to be created
"phone": {
".read": "auth != null" // Only allow authenticated users to read phone number
},
"state": {
".read": "auth != null", // Only allow authenticated users to read approval state
".write": "auth != null" // Only allow authenticated users to change state
}
}
}
}
}
my-firebase
|
`- nominations
|
`- entries
| |
| `- private
| `- public
|
`- status
|
`- pending
`- approved
`- rejected
子规则(例如,$提名
)不会阻止从父项读取整个子项。如果我听了child\u添加了,它会愉快地返回所有孩子和他们的所有数据,即使有上述安全规则
我目前的解决方案是保留一个名为approved
的单独节点,并在有人批准或拒绝提名时在列表之间移动数据,但这似乎是一种非常糟糕的方法
更新
下面是我的精彩评论,我用最少的努力重新实现了最初的想法
新的数据结构如下:
{
"rules": {
"nominations": {
".read": true,
"$nominationId": {
".read": "data.child('state').val() == 'approved' || auth != null", // Only read approved nominations if not authenticated
".write": "!data.exists()", // Only allow new nominations to be created
"phone": {
".read": "auth != null" // Only allow authenticated users to read phone number
},
"state": {
".read": "auth != null", // Only allow authenticated users to read approval state
".write": "auth != null" // Only allow authenticated users to change state
}
}
}
}
}
my-firebase
|
`- nominations
|
`- entries
| |
| `- private
| `- public
|
`- status
|
`- pending
`- approved
`- rejected
每个提名都存储在条目
下,私人数据如电话号码、电子邮件等。私人数据存储在私人
下,公开数据存储在公共
下
更新后的规则如下:
{
"rules": {
"nominations": {
".read": true,
"$nominationId": {
".read": "data.child('state').val() == 'approved' || auth != null", // Only read approved nominations if not authenticated
".write": "!data.exists()", // Only allow new nominations to be created
"phone": {
".read": "auth != null" // Only allow authenticated users to read phone number
},
"state": {
".read": "auth != null", // Only allow authenticated users to read approval state
".write": "auth != null" // Only allow authenticated users to change state
}
}
}
}
}
my-firebase
|
`- nominations
|
`- entries
| |
| `- private
| `- public
|
`- status
|
`- pending
`- approved
`- rejected
{
“规则”:{
“提名”:{
“条目”:{
“$id”:{
“.write”:“!data.exists()”,
“公众”:{
“.read”:正确,
},
“私人”:{
.read:“auth!=null”
}
}
},
“地位”:{
“待定”:{
“.read”:“auth!=null”,
“$id”:{
.write:“root.child('namignations/entries').child($id.exists()&&(auth!=null | | newData.val()=true)”
}
},
“批准”:{
“.read”:正确,
“$id”:{
.write:“root.child('提名/条目').child($id.exists()&&auth!=null”
}
},
“拒绝”:{
“.read”:“auth!=null”,
“$id”:{
.write:“root.child('提名/条目').child($id.exists()&&auth!=null”
}
}
}
}
}
}
以及JavaScript实现:
var db=new Firebase('https://my.firebaseio.com')
变量提名=db.child('提名')
var entries=namignations.child('entries')
变量状态=提名。子项('状态')
var pending=status.child('pending')
var approved=状态。子级(“approved”)
var rejected=status.child('rejected')
//通过表单输入创建提名(未显示)
var createNamement=函数(){
风险值数据={
公众:{
名称:“Foo”,
年龄:20
},
私人:{
createdAt:new Date().getTime(),
电话:123456
}
}
var提名=条目。推送()
提名.setWithPriority(data,data.private.createdAt)
挂起.child(提名.name()).set(true)
}
//检索当前提名状态
var getStatus=函数(id,回调){
已批准.child(id).once('value',函数(快照){
if(snapshot.val()){
回调(id为“已批准”)
}否则{
拒绝.child(id).once('value',函数(快照){
回调(id,snapshot.val()?“已拒绝”:“挂起”)
})
}
})
}
//更改提名状态
var changeStatus=函数(id、from、to){
status.child(from).child(id).remove()
status.child(to).child(id).set(true)
}
我正在努力解决的唯一一个实现部分是处理状态更改,我当前的方法肯定可以改进:
\每个([待定、批准、拒绝])功能(状态){
状态.on('child_added',函数(快照){
$('#'+snapshot.name()).removeClass('pending approved rejected').addClass(status.name())
})
})
我计划在提名/状态
上使用child\u changed
,但我无法让它可靠地工作。如果我完全摸索安全规则的工作方式(我只是自己学习),那么当任何一条规则允许访问时,访问都被授予。因此,其内容如下:
{
"rules": {
"nominations": {
".read": true,
"$nominationId": {
".read": "data.child('state').val() == 'approved' || auth != null", // Only read approved nominations if not authenticated
".write": "!data.exists()", // Only allow new nominations to be created
"phone": {
".read": "auth != null" // Only allow authenticated users to read phone number
},
"state": {
".read": "auth != null", // Only allow authenticated users to read approval state
".write": "auth != null" // Only allow authenticated users to change state
}
}
}
}
}
my-firebase
|
`- nominations
|
`- entries
| |
| `- private
| `- public
|
`- status
|
`- pending
`- approved
`- rejected
- 提名“.read”:正确,授予访问权限
- 其他规则:不要阅读
此外,如果删除了该规则,$namignionid
”.read“在记录被批准的情况下授予访问权限;因此,手机中的.read
和状态
一旦获得批准就变得多余
将其分解为public/
和private/
子项可能是最简单的,如下所示:
nominations/unapproved/ # only visible to logged in users
nominations/approved/ # visible to anyone (move record here after approval)
nominations/approved/public/ # things everyone can see
nominations/approved/restricted/ # things like phone number, which are restricted
更新
再想一想,我想你仍然会遇到一个问题,那就是将approved/
公开,这将允许你列出记录,并将approved/restricted/
私有化。在这个用例中,受限制的数据可能也需要它自己的路径。加藤是对的。重要的是要了解安全规则从不过滤数据。对于任何位置,您都可以读取所有数据(包括其子项),或者不读取任何数据。因此,在您的规则中,“提名”下的“.read”:true否定了所有其他规则
所以我推荐的方法是有3个列表。一个包含提名数据,一个包含核准提名列表,一个包含待提名列表
你的规则可以是这样的:
{
"rules": {
// The actual nominations. Each will be stored with a unique ID.
"nominations": {
"$id": {
".write": "!data.exists()", // anybody can create new nominations, but not overwrite existing ones.
"public_data": {
".read": true // everybody can read the public data.
},
"phone": {
".read": "auth != null", // only authenticated users can read the phone number.
}
}
},
"approved_list": {
".read": true, // everybody can read the approved nominations list.
"$id": {
// Authenticated users can add the id of a nomination to the approved list
// by creating a child with the nomination id as the name and true as the value.
".write": "auth != null && root.child('nominations').child($id).exists() && newData.val() == true"
}
},
"pending_list": {
".read": "auth != null", // Only authenticated users can read the pending list.
"$id": {
// Any user can add a nomination to the pending list, to be moderated by
// an authenticated user (who can then delete it from this list).
".write": "root.child('nominations').child($id).exists() && (newData.val() == true || auth != null)"
}
}
}
}
未经身份验证的用户可以添加具有以下内容的新提名:
var id = ref.child('nominations').push({ public_data: "whatever", phone: "555-1234" });
ref.child('pending_list').child(id).set(true);
认证用户公司