Firebase 实时安全规则:无法将 uid 与叶值进行比较

Firebase Realtime security rules: unable to compare uid with leaf value

我正在尝试配置 Firebase Realtime 以检查用户是否应该有权注册。

为此,我在每个名为“uid”的寄存器中都有一个值,其中包含可以访问它的用户的 uid。

按照我的逻辑,这条规则应该足够了,但它拒绝访问 Usuarios,即使它们将 uid 与 auth.uid 匹配。

{
  "rules": {     
            "Usuarios" :{      
                "$usuarioPk" : {
                ".read": "data.child('uid').val() == auth.uid"

                }
           }
  }
}

¿我做错了什么?

编辑:这是代码(C# - Unity 游戏引擎)。

基础ClassFirebaseTable.cs

public class FirebaseTable : MonoBehaviour
{
Firebase.Auth.FirebaseAuth auth;
Firebase.FirebaseApp app;

private void Awake()
{


}


protected UnityEvent onDataUpdate = new UnityEvent();

public string dbPath = "";


protected virtual void OnEnable()
{
    IniciarListenerDB();
}

protected virtual void OnDisable()
{
    DetenerListenerDB();
}


#region Iniciar/Detener Listeners


void IniciarListenerDB()
{
    FirebaseDatabase.DefaultInstance
        .GetReference(dbPath)
        .ValueChanged += HandleValueChanged;
        
}

void DetenerListenerDB()
{
    FirebaseDatabase.DefaultInstance
        .GetReference(dbPath)
        .ValueChanged -= HandleValueChanged;

}
#endregion

#region Receptor de actualizaciones

/// <summary>
/// 
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
protected virtual void HandleValueChanged(object sender, ValueChangedEventArgs args)
{

}
#endregion

这里是childclass

public class TablaUsuarios : FirebaseTable
{

public List<Usuario> usuarios;


protected override void OnEnable()
{
    base.OnEnable();
    dbPath = "Usuarios";
    if(usuarios == null)
    {
        usuarios = new List<Usuario>();
    }

}

protected override void OnDisable()
{
    base.OnDisable();
    usuarios.Clear();

}

protected override void HandleValueChanged(object sender, ValueChangedEventArgs args)
{
    DataSnapshot dataSnapshot = args.Snapshot;

    if(args.DatabaseError != null)
    {
        Debug.LogError(args.DatabaseError.Message);
    }
    

    List<Usuario> entitiesDB = DataSnapshotToList(dataSnapshot);
    usuarios = entitiesDB;
    //UpdatePublicList(entitiesDB, ref usuarios);


}


List<Usuario> DataSnapshotToList(DataSnapshot dataSnapshot)
{
    List<Usuario> result = new List<Usuario>();
    foreach(var children in dataSnapshot.Children)
    {
        if (children.Value is IDictionary<string, object> variables)
        {
            Debug.Log(dataSnapshot.GetRawJsonValue());
            Usuario entity = new Usuario();
            entity.pk = (string)variables["pk"];
            entity.uid = (string)variables["uid"];
            entity.nombre = (string)variables["nombre"];
            entity.apellidos = (string)variables["apellidos"];
            entity.email = (string)variables["email"];
            entity.telefono = (string)variables["telefono"];
            entity.tipoUsuario = (string)variables["tipoUsuario"];

            entity.skContrato = (string)variables["skContrato"];

            result.Add(entity);
        }
    }
    

    return result;
}

void UpdatePublicList(List<Usuario> firebaseEntities, ref List<Usuario> localEntities)
{
    List<Usuario> usuariosToCreate = new List<Usuario>(); // Añadiremos los usuarios que deben ser creados
    List<Usuario> usuariosToUpdate = new List<Usuario>(); // Añadiremos los usuarios que deben ser actualizados
    List<Usuario> usuariosToDelete = new List<Usuario>(); // Añadiremos los usuarios que deben ser eliminados

    foreach (var element in localEntities) // Creamos una lista con los usuarios a eliminar
    {
        usuariosToDelete.Add(element);
    }

    foreach(var firebaseElement in firebaseEntities) // Iteramos por la lista publica de usuarios
    {
        if (!UsuarioExist(firebaseElement.pk, localEntities)) // Si no la encontramos
        {
            usuariosToCreate.Add(firebaseElement);

        }
        else if (UsuarioExist(firebaseElement.pk, localEntities)) // Si la encontramos pero ha cambiado
        {
            usuariosToUpdate.Add(firebaseElement);

        }
    }

    foreach(var localElement in localEntities)
    {
        if(!UsuarioExist(localElement.pk, firebaseEntities))
        {
            usuariosToDelete.Add(localElement);
        }
    }

    for(int i = 0; i < usuariosToDelete.Count; i++)
    {
        usuarios.Remove(FindUsuario(usuariosToDelete[i].pk, usuarios));
    }

    for (int i = 0; i < usuariosToCreate.Count; i++)
    {
        usuarios.Add(usuariosToCreate[i]);
    }

    for (int i = 0; i < usuariosToUpdate.Count; i++)
    {
        FindUsuario(usuariosToUpdate[i].pk, usuarios).CopyDataFrom(usuariosToUpdate[i]);
    }


}

public Usuario FindUsuario(string pk, List<Usuario> data)
{
    

    foreach(var usuario in usuarios)
    {
        if(usuario.Pk == pk)
        {
            return usuario;
        }
    }

    return null;
    
}

public bool UsuarioExist(string pk, List<Usuario> data)
{
    if(FindUsuario(pk, data) != null)
    {
        return true;
    }
    return false;
}



// Start is called before the first frame update
void Start()
{
    
}

// Update is called once per frame
void Update()
{
    
}
}

和错误日志:

This client does not have permission to perform this operation. UnityEngine.Debug:LogError (object) TablaUsuarios:HandleValueChanged (object,Firebase.Database.ValueChangedEventArgs) (at Assets/Scripts/Tablas Firebase/NuevoSistema/Tables/TablaUsuarios.cs:36) Firebase.Database.Internal.InternalValueListener/c__AnonStorey1:<>m__0 () (at Z:/tmp/tmp.gpjxyegeCh/firebase/database/client/unity/proxy/InternalValueListener.cs:72) Firebase.ExceptionAggregator:Wrap (System.Action) (at Z:/tmp/tmp.AqqnQIVt80/firebase/app/client/unity/src/Platform/ExceptionAggregator.cs:112) Firebase.Database.Internal.InternalValueListener:OnCancelledHandler (int,Firebase.Database.Internal.Error,string) (at Z:/tmp/tmp.gpjxyegeCh/firebase/database/client/unity/proxy/InternalValueListener.cs:65) Firebase.AppUtil:PollCallbacks () (at Z:/tmp/tmp.RYyft9kBZb/firebase/app/client/unity/proxy/AppUtil.cs:32) Firebase.Platform.FirebaseAppUtils:PollCallbacks () (at Z:/tmp/tmp.RYyft9kBZb/firebase/app/client/unity/proxy/FirebaseAppUtils.cs:33) Firebase.Platform.FirebaseHandler:Update () (at Z:/tmp/tmp.AqqnQIVt80/firebase/app/client/unity/src/Unity/FirebaseHandler.cs:208) Firebase.Platform.FirebaseMonoBehaviour:Update () (at Z:/tmp/tmp.AqqnQIVt80/firebase/app/client/unity/src/Unity/FirebaseMonoBehaviour.cs:45)

您的代码正在尝试读取 /Usarios 节点。但是如果我们查看规则,没有人有权读取 /Usarios 节点,因此读取操作会(正确地)被拒绝。

此错误的一个常见来源是 rules do not filter data。相反,规则仅检查是否允许您尝试执行的操作。

如果您想安全地过滤数据,则必须在规则和代码中对条件进行编码,如 query based rules 上的文档所示。这可能是:

"Usarios": {
  ".read": "auth.uid != null &&
            query.orderByChild == 'uid' &&
            query.equalTo == auth.uid" // restrict profile access to owner of the profile
}