英文:
Firebase real-time database rules
问题
以下是翻译好的部分:
这是我的示例数据库:
{
"referrals": {
"Nr7sS4xV1fO59wjCqbEabLlK8RF3": {
"16-10-2020": {
"-MJhjQddWdWDImj98Sov": {
"city": "hyhy",
"name": "mmmm",
"number": "03058852844",
"remarks": "pg"
},
"-MJhmeRiqeXskncHJF61": {
"city": "vsva",
"name": "yhyh",
"number": "02089453882",
"remarks": "pg"
}
},
"total_referrals": 2
},
"jpeoZQAPdZY4yEt8yGifGZi4U4r1": {
"16-10-2020": {
"-MJlzrS8xX8MGN1ar9uw": {
"city": "lahore",
"name": "khursand",
"number": "03014181394",
"remarks": "paid"
},
"-MJm-LFhEEMBzBPRftlC": {
"city": "lahore",
"name": "khursand",
"number": "03014141111",
"remarks": "pg"
}
},
"total_referrals": 2
}
},
"users": {
"Nr7sS4xV1fO59wjCqbEabLlK8RF3": {
"account_status": "Level 1",
"current_balance": "0",
"isBan": false,
"paid_referrals": "0",
"total_balance": "0",
"total_withdraw": "0"
},
"jpeoZQAPdZY4yEt8yGifGZi4U4r1": {
"account_status": "Level 1",
"current_balance": "0",
"paid_referrals": "0",
"total_balance": "0",
"total_withdraw": "0"
}
},
"withdraw_details": {
"Nr7sS4xV1fO59wjCqbEabLlK8RF3": {
"-MJMgVd3TuWYjdGSd-FY": {
"amount": "600",
"date": "11/10/2020",
"method": "Easypaisa",
"number": "03058853833",
"tid": "90124678573"
}
},
"jpeoZQAPdZY4yEt8yGifGZi4U4r1": {
"-MJm7SfTwWafae85ayRq": {
"amount": "600",
"date": "11/10/2020",
"method": "Easypaisa",
"number": "03494628929",
"tid": "90124678573"
}
}
}
}
这是我在控制台中尝试设置的数据库规则:
{
"rules": {
"users": {
"$user_id": {
".read": "$user_id == auth.uid && auth != null",
".write": false
}
},
"withdraw_details": {
"$user_id": {
".read": "$user_id == auth.uid && auth != null",
".write": false
}
},
"referrals": {
"$user_id": {
".read": "$user_id == auth.uid && auth != null",
".write": "$user_id == auth.uid && auth != null",
"$date": {
".validate": "newData.hasChildren(['name', 'number', 'city', 'remarks'])",
"name": {".validate": "newData.isString() && newData.val().length <= 30"},
"number": {".validate": "newData.isNumber() && newData.val().length == 11"},
"city": {".validate": "newData.isString() && newData.val().length <= 20"},
"remarks": {".validate": "newData.isString() && newData.val().length <= 15"},
"$other": {".validate": false}
}
}
}
}
}
此外,进一步澄清,我希望/users/uid/ 和 /withdraw_details/uid/ 只能由其所有者进行读取,auth 不应为 null。对于这些位置的写访问应该被拒绝。
/referrals/uid/ 位置应该对其所有者具有读和写访问权限,并且应满足上述数据库规则中的某些标准和验证要求。
英文:
Here is my example database:
{
"referrals" : {
"Nr7sS4xV1fO59wjCqbEabLlK8RF3" : {
"16-10-2020" : {
"-MJhjQddWdWDImj98Sov" : {
"city" : "hyhy",
"name" : "mmmm",
"number" : "03058852844",
"remarks" : "pg"
},
"-MJhmeRiqeXskncHJF61" : {
"city" : "vsva",
"name" : "yhyh",
"number" : "02089453882",
"remarks" : "pg"
}
},
"total_referrals" : 2
},
"jpeoZQAPdZY4yEt8yGifGZi4U4r1" : {
"16-10-2020" : {
"-MJlzrS8xX8MGN1ar9uw" : {
"city" : "lahore",
"name" : "khursand",
"number" : "03014181394",
"remarks" : "paid"
},
"-MJm-LFhEEMBzBPRftlC" : {
"city" : "lahore",
"name" : "khursand",
"number" : "03014141111",
"remarks" : "pg"
}
},
"total_referrals" : 2
}
},
"users" : {
"Nr7sS4xV1fO59wjCqbEabLlK8RF3" : {
"account_status" : "Level 1",
"current_balance" : "0",
"isBan" : false,
"paid_referrals" : "0",
"total_balance" : "0",
"total_withdraw" : "0"
},
"jpeoZQAPdZY4yEt8yGifGZi4U4r1" : {
"account_status" : "Level 1",
"current_balance" : "0",
"paid_referrals" : "0",
"total_balance" : "0",
"total_withdraw" : "0"
}
},
"withdraw_details" : {
"Nr7sS4xV1fO59wjCqbEabLlK8RF3" : {
"-MJMgVd3TuWYjdGSd-FY" : {
"amount" : "600",
"date" : "11/10/2020",
"method" : "Easypaisa",
"number" : "03058853833",
"tid" : "90124678573"
}
},
"jpeoZQAPdZY4yEt8yGifGZi4U4r1" : {
"-MJm7SfTwWafae85ayRq" : {
"amount" : "600",
"date" : "11/10/2020",
"method" : "Easypaisa",
"number" : "03494628929",
"tid" : "90124678573"
}
}
}
}
And here are my database rules that I've tried to set in console:
{
"rules": {
"users":{
"$user_id":{
".read": "$user_id == auth.uid && auth != null", // only owner or authenticated user can read
".write": false // No-one can write
}
},
"withdraw_details":{
"$user_id":{
".read": "$user_id == auth.uid && auth != null",// only owner or authenticated user can read
".write": false // No-one can write
}
},
"referrals": {
"$user_id": {
".read": "$user_id == auth.uid && auth != null", // same as above
".write": "$user_id == auth.uid && auth != null", // owner and authenticated can write
"$date": {
// children should be only these
".validate": "newData.hasChildren(['name', 'number', 'city', 'remarks'])",
// you can see further validation rules below
"name": {".validate": "newData.isString() && newData.val().length <= 30"},
"number": {".validate": "newData.isNumber() && newData.val().length == 11"},
"city": {".validate": "newData.isString() && newData.val().length <= 20"},
"remarks": {".validate": "newData.isString() && newData.val().length <= 15"},
// any other child should be rejected
"$other": {".validate": false}
}
}
}
}
Now I don't know what I am doing wrong here because every time I try to read any child it throws a "Permission denied" error.
Like a user details request below
private void getDetails() {
databaseReference.child("users").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
if (snapshot.hasChild(mAuth.getCurrentUser().getUid())) {
AccountDetails accountDetails = snapshot
.child(mAuth.getCurrentUser().getUid())
.getValue(AccountDetails.class);
setValuesToTextViews(
accountDetails.getTotal_balance(),
accountDetails.getTotal_withdraw(),
accountDetails.getCurrent_balance(),
accountDetails.getAccount_status(),
accountDetails.getPaid_referrals(),
accountDetails.getTotal_referrals()
);
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Log.w(TAG, "onCancelled: " + error.toException());
Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
Moreover, on further clarification, I want the /users/uid/ && /withdraw_details/uid/ to be read only by it's owner and auth shouldn't be null. and write access to these locations should be denied.
The /referrals/uid/ location should have read and write access to its owner and with certain criteria and validations as you can see in the database rules above.
答案1
得分: 0
安全规则本身不会过滤数据。相反,它们只是强制执行允许对数据库执行的任何操作。
因此,在您的代码中,您会将侦听器附加到 /users
:
databaseReference.child("users").addListenerForSingleValueEvent(new ValueEventListener() {
当您这样做时,规则引擎会检查该用户是否具有对 /users
的读取权限。由于没有人对 /users
具有读取权限,它会拒绝该操作。
相反,您希望为特定用户读取节点:
databaseReference.child("users").child(mAuth.getCurrentUser().getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
AccountDetails accountDetails = snapshot.getValue(AccountDetails.class);
setValuesToTextViews(
accountDetails.getTotal_balance(),
accountDetails.getTotal_withdraw(),
accountDetails.getCurrent_balance(),
accountDetails.getAccount_status(),
accountDetails.getPaid_referrals(),
accountDetails.getTotal_referrals()
);
}
...
有关更多信息,请参阅 Firebase 文档中的规则不是过滤器,关于此主题的搜索结果,以及例如:使用安全规则限制子节点/字段访问权限。
英文:
Security rules on their own don't filter data. Instead they merely enforce that any operation you perform on the database is allowed.
So in your code, you attach a listener to /users
:
databaseReference.child("users").addListenerForSingleValueEvent(new ValueEventListener() {
When you do this, the rules engine checks if this user has read permission on /users
. And since nobody has read permission on /users
it rejects the operation.
What you'll want to do instead is read the node for the specific user:
databaseReference.child("users").child(mAuth.getCurrentUser().getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
AccountDetails accountDetails = snapshot.getValue(AccountDetails.class);
setValuesToTextViews(
accountDetails.getTotal_balance(),
accountDetails.getTotal_withdraw(),
accountDetails.getCurrent_balance(),
accountDetails.getAccount_status(),
accountDetails.getPaid_referrals(),
accountDetails.getTotal_referrals()
);
}
...
For more on this, see the Firebase documentation on rules are not filters, these search results about the topic and for example: Restricting child/field access with security rules
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论