android - protect - ¿Es segura la forma en que el inicio rápido de la base de datos de Firebase maneja los recuentos?
protect firebase database (1)
Las reglas de seguridad pueden hacer algunas cosas:
-
asegúrese de que un usuario solo pueda agregar / eliminar su propio
uid
al nodo destars
"stars": { "$uid": { ".write": "$uid == auth.uid" } }
-
asegúrese de que un usuario solo pueda cambiar
starCount
cuando agregue su propiouid
al nodo destars
o lo elimine de allí -
asegúrese de que el usuario solo pueda aumentar / disminuir
starCount
en 1
Incluso con estos, de hecho podría ser complicado tener una regla de seguridad que garantice que
starCount
sea igual al número de uids en el nodo de
stars
.
Sin embargo, te animo a que lo pruebes y compartas tu resultado.
La forma en que he visto a la mayoría de los desarrolladores lidiar con esto es:
-
empiece a contar con el cliente (si el tamaño del nodo de
stars
no es demasiado grande, esto es razonable). -
tener un proceso confiable que se ejecute en un servidor que agregue las
stars
enstarCount
. Podría usar eventos child_added / child_removed para incrementar / decrementar.
Actualización: con ejemplo de trabajo
Escribí un ejemplo funcional de un sistema de votación. La estructura de datos es:
votes: {
uid1: true,
uid2: true,
},
voteCount: 2
Cuando un usuario vota, la aplicación envía una actualización de múltiples ubicaciones:
{
"/votes/uid3": true,
"voteCount": 3
}
Y luego para eliminar su voto:
{
"/votes/uid3": null,
"voteCount": 2
}
Esto significa que la aplicación necesita leer explícitamente el valor actual de
voteCount
, con:
function vote(auth) {
ref.child(''voteCount'').once(''value'', function(voteCount) {
var updates = {};
updates[''votes/''+auth.uid] = true;
updates.voteCount = voteCount.val() + 1;
ref.update(updates);
});
}
Es esencialmente una transacción de múltiples ubicaciones, pero luego incorpora el código de la aplicación y las reglas de seguridad en lugar del Firebase SDK y el servidor en sí.
Las reglas de seguridad hacen algunas cosas:
- asegúrese de que voteCount solo pueda subir o bajar 1
- asegurarse de que un usuario solo pueda agregar / eliminar su propio voto
- Asegurarse de que un aumento de conteo vaya acompañado de un voto
- asegúrese de que una disminución del recuento vaya acompañada de un "no votado"
- Asegurarse de que una votación vaya acompañada de un aumento de conteo
Tenga en cuenta que las reglas no:
-
asegúrese de que un "no votado" vaya acompañado de una disminución de conteo (se puede hacer con una regla
.write
) - reintentar votos fallidos / desestimaciones (para manejar votaciones / desestimaciones concurrentes)
Las normas:
"votes": {
"$uid": {
".write": "auth.uid == $uid",
".validate": "(!data.exists() && newData.val() == true &&
newData.parent().parent().child(''voteCount'').val() == data.parent().parent().child(''voteCount'').val() + 1
)"
}
},
"voteCount": {
".validate": "(newData.val() == data.val() + 1 &&
newData.parent().child(''votes'').child(auth.uid).val() == true &&
!data.parent().child(''votes'').child(auth.uid).exists()
) ||
(newData.val() == data.val() - 1 &&
!newData.parent().child(''votes'').child(auth.uid).exists() &&
data.parent().child(''votes'').child(auth.uid).val() == true
)",
".write": "auth != null"
}
jsbin con algún código para probar esto: http://jsbin.com/yaxexe/edit?js,console
Quiero crear un campo de incremento para los me gusta del artículo.
Me refiero a este enlace: https://firebase.google.com/docs/database/android/save-data#save_data_as_transactions
En el ejemplo hay código para el campo de incremento:
if (p.stars.containsKey(getUid())) {
// Unstar the post and remove self from stars
p.starCount = p.starCount - 1;
p.stars.remove(getUid());
} else {
// Star the post and add self to stars
p.starCount = p.starCount + 1;
p.stars.put(getUid(), true);
}
Pero, ¿cómo puedo estar seguro si el usuario ya le gustó / no le gustó el artículo?
En el ejemplo, el usuario (pirata informático) también podría borrar estrellas completas Mapa como este y se guardará de todos modos:
p.stars = new HashMap<>();
y arruinará la lógica para otros usuarios a quienes ya les gustó.
Ni siquiera creo que pueda establecer reglas para esto, especialmente para la acción de "disminución de conteo".
¿Alguna ayuda, sugerencias?