问题描述
继续上我为应用程序设计了以下内容。
设计
- 可以登录到应用程序的用户
- 登录的用户可以创建客户,并将其存储在节点下,该节点的值将是当前登录的用户ID。
这是我通过Android应用程序添加数据的方式。
FirebaseInstance mFirebaseInstance = FirebaseDatabase.getInstance();
FirebaseDatabase mFirebaseDatabase = mFirebaseInstance.getReference("tbl-customers").child(FirebaseAuth.getInstance().getCurrentUser().getUid());
//This will create or fetch user id node under tbl-customers.
btnSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String name = inputName.getText().toString();
String email = inputCode.getText().toString();
String limit= inputLimit.getText().toString();
createUser(name, email,limit);
}
});
private void createUser(String name, String email,String limit) {
userId = mFirebaseDatabase.push().getKey();
Customer customer = new Customer(name, email,limit);
mFirebaseDatabase.child(userId).setValue(customer);
}
就是这样。在数据库中,它的表示方式如下:
tbl-customers
|___loggedInUserId1
|___customerID1
|___customerName
|___customerCode
|___customerLimit
|___customerID2
|___customerName
|___customerCode
|___customerLimit
|___customerID3
|___customerName
|___customerCode
|___customerLimit
|___loggedInUserId2
|___customerID4
|___customerName
|___customerCode
|___customerLimit
我有定义为
{
"rules": {
"tbl-customers": {
".read": "auth != null",
".write": "auth != null",
"$custId": {
"customerName": {
".validate": "newData.isString() && newData.val().length < 100 && newData.val().length > 8"
},
"customerCode": {
".validate": "newData.isString() && newData.val().length<4 && !newData.exists() && newData.val().length>1"
},
"customerLimit": {}
}
}
}
}
不幸的是,插入数据时没有考虑为每个属性编写的任何验证。 即使是空数据也会被插入 。
我开始考虑所写的规则是否具有正确的结构,因为如果我看到插入的数据,则它具有3个级别tbl-customer-->loggedInUserId-->customerId但是规则仅针对tbl-customer-->customerId编写。
因此,我更改了以下rules 。
{
"rules": {
"tbl-customers": {
".read": "auth != null",
".write": "auth != null",
"$user_id": {
".validate": "auth.uid===$user_id",
"$custId": {
"customerName": {
".validate": "newData.isString() && newData.val().length < 100"
},
"customerCode": {
".validate": "newData.isString() && newData.val().length<4 && !newData.exists()"
},
"customerLimit": {}
}
}
}
}
}
通过包括以下内容将其扩展到另一个层次:
"$user_id": {
".validate": "auth.uid===$user_id"
...
}
但是现在这会引发“ Permission Denied异常”。
在这个时间点上我没有主意了。
有人可以指引我正确的方向吗?
我从上一个问题中引用了很多帖子,但是很糟糕,我无法从中获取很多信息。
希望找到关于为什么规则验证失败以及为什么使用上述第一个规则插入数据的明确解释。
1楼
我在这里可能是错的,但是无论在什么地方,.read和.write规则将始终在您的树上向下层叠,最容易出现问题的地方是“ .write”:“ auth!= null”行。
最好将此规则移至“ .validate”:“ auth.uid === $ user_id”规则所在的位置,然后删除验证规则。 然后,您将其更改为“ auth.uid == $ user_id”。 我认为“验证”规则仅是在特定位置接受书面输入,然后接受或拒绝。
我认为这应该是这样:
{
"rules": {
"tbl-customers": {
".read": "auth != null"
"$user_id": {
".write": "auth.uid === $user_id"
"$custId": {
"customerName": {
".validate": "newData.isString() && newData.val().length < 100"
},
"customerCode": {
".validate": "newData.isString() && newData.val().length<4 && !newData.exists()"
},
"customerLimit": {}
}
}
}
}
}
此结构将允许所有已登录的用户读取数据,您可以根据需要进一步限制到$ user_id位置,类似于当前的写入规则。 然后,这将仅允许与$ user_id匹配的用户具有读取和写入权限。
案例分析
除此之外,这是我之前建立的结构,管理员可以通过该结构添加用户:
{
"rules": {
"Administrator": {
".read": "auth != null"
},
"Users": {
"$user_id": {
".write": "$user_id === auth.uid",
".read": "$user_id === auth.uid"
}
}
}
}