Android Firebase数据库-限制每个用户仅更新一次值
我在android应用程序中使用Firebase实时数据库, 该应用程序包含文章,我想通过所有应用程序用户向文章添加视图数 数据库包含一个子项(ViewScont)及其值(是一个数字) 我需要在新用户每次查看文章时更新该值(增加1)(概念类似于YouTube视频视图) 用户必须通过匿名身份验证才能更新该值,但不能多次进行验证 我将逻辑集成到应用程序中来实现这一点,效果非常好。 但我担心的是,如果有人试图连接到我的应用程序之外的数据库(使用他们自己的代码),并不断增加值 我目前的安全规则是:Android Firebase数据库-限制每个用户仅更新一次值,android,firebase-realtime-database,firebase-security,Android,Firebase Realtime Database,Firebase Security,我在android应用程序中使用Firebase实时数据库, 该应用程序包含文章,我想通过所有应用程序用户向文章添加视图数 数据库包含一个子项(ViewScont)及其值(是一个数字) 我需要在新用户每次查看文章时更新该值(增加1)(概念类似于YouTube视频视图) 用户必须通过匿名身份验证才能更新该值,但不能多次进行验证 我将逻辑集成到应用程序中来实现这一点,效果非常好。 但我担心的是,如果有人试图连接到我的应用程序之外的数据库(使用他们自己的代码),并不断增加值 我目前的安全规则是: "V
"ViewsCount"
{
".write": "newData.exists() && auth!==null",
".validate" "newData.val()===data.val()+1"
}
"users": {
"$user_id": {
".write": "auth.uid===$user_id",
".read": "auth.uid===$user_id ",
}
}
是否有办法通过安全规则将该值的更新限制为每个用户仅更新一次?。
错误:
更新:
当然有,但你得做些额外的工作。第一件事是在数据库中跟踪已经看过每篇文章的人。例如,保存他们的UID列表,如下所示:
viewedBy: {
uidOfKarim: true,
uidOfPuf: true
}
现在,当有人查看一篇文章时,他们会将UID写入viewedBy
,同时增加该文章的查看次数。在代码中,可以简单到:
DatabaseReference countRef = FirebaseDatabase.getInstance().getReference("ViewsCount");
countRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String uid = FirebaseAuthentication.getCurrentUser().getUid();
Long newCount = dataSnapshot.getValue(Long.class) + 1;
Map<String, Object> updates = new HashMap<String, Object>();
updates.put("viewedBy/"+uid, true);
updates.put("ViewsCount", newCount);
}
@Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
语法有点长,因为它同时检查ViewScont
和ViewedBy
数据。只有当写入增量为1且来自尚未计数的用户时,写入才会成功。如果它们之前已经计数过,或者没有增加1,则写入将被拒绝
这里有一种边缘情况:如果多个用户几乎同时查看,他们的一次写入可能会被拒绝,因为他们实际上没有增加值:
user1 user2 database
| | |
read_count -------------------> |
| | |
| read_count --------> |
| | |
| <------------------- 2 |
| | |
| | <------------ 2 |
| | |
set_count 3 -------------------> |
| | |
| set_count --------> |
| | |
| <------------------- ok |
| | |
| | <------------ ACCESS |
| | DENIED |
| | |
这是在任何其他人有相同问题时起作用的安全规则:
{"rules": {
"views": {
".write": "auth != null",
".validate": "newData.hasChildren(['ViewsCount', 'viewedBy'])",
"ViewsCount": {
".read": "auth != null",
".validate":"data.parent().child('viewedBy').child(auth.uid).exists()== false"
},
"viewedBy": {
"$user_id": {
".validate": " auth.uid===$user_id && !data.exists() && newData.exists() &&
newData.parent().parent().child('ViewsCount').val() ===
data.parent().parent().child('ViewsCount').val()+1
&& newData.val()===true"}},
},
谢谢,但这里的问题和我所担心的是,如果其他人出于恶意编写了一个不同的代码,他在不将UID添加到节点“viewdBy”的情况下,将ViewScont值的增量增加到他想要的次数。他只需要反编译应用程序,提取json文件,然后用相同的包名编写自己的代码。我想我要问的是,在ViewScont增加后,是否可以强制将查看器UID添加到viewdBy节点。由于只有我可以访问和更改这些安全规则,因此,如果不将UID写入查看的,则无法进行增量操作,每个用户只能根据相同的规则执行一次。请尝试一下,如果它不起作用,请告诉我。我会感谢您。“.value”:返回一个错误(错误保存规则-第23行:应为“{”)。您的意思是“.validate”?
"52469568": {
"ViewsCount": 10,
}
{"rules": {
"views": {
".write": "auth != null",
".validate": "newData.hasChildren(['ViewsCount', 'viewedBy'])",
"ViewsCount": {
".read": "auth != null",
".validate":"data.parent().child('viewedBy').child(auth.uid).exists()== false"
},
"viewedBy": {
"$user_id": {
".validate": " auth.uid===$user_id && !data.exists() && newData.exists() &&
newData.parent().parent().child('ViewsCount').val() ===
data.parent().parent().child('ViewsCount').val()+1
&& newData.val()===true"}},
},