【问题标题】:Firebase Realtime security rules: unable to compare uid with leaf valueFirebase 实时安全规则:无法将 uid 与叶值进行比较
【发布时间】:2021-12-25 01:55:31
【问题描述】:

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

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

  • 数据树是“(root/)Usuaros/$userid”。
  • 每个 $userid 都有一个名为“uid”的叶子,其中包含一个字符串值。

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

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

                }
           }
  }
}

¿我做错了什么?

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

基类 FirebaseTable.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

这是子类

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()
{
    
}
}

还有错误日志:

此客户端无权执行此操作。 UnityEngine.Debug:LogError(对象) TablaUsuarios:HandleValueChanged (object,Firebase.Database.ValueChangedEventArgs) (在 Assets/Scripts/Tablas Firebase/NuevoSistema/Tables/TablaUsuarios.cs:36) Firebase.Database.Internal.InternalValueListener/c__AnonStorey1:m__0 () (在 Z:/tmp/tmp.gpjxyegeCh/firebase/database/client/unity/proxy/InternalValueListener.cs:72) Firebase.ExceptionAggregator:Wrap (System.Action) (在 Z:/tmp/tmp.AqqnQIVt80/firebase/app/client/unity/src/Platform/ExceptionAggregator.cs:112) Firebase.Database.Internal.InternalValueListener:OnCancelledHandler (int,Firebase.Database.Internal.Error,string) (在 Z:/tmp/tmp.gpjxyegeCh/firebase/database/client/unity/proxy/InternalValueListener.cs:65) Firebase.AppUtil:PollCallbacks () (在 Z:/tmp/tmp.RYyft9kBZb/firebase/app/client/unity/proxy/AppUtil.cs:32) Firebase.Platform.FirebaseAppUtils:PollCallbacks () (在 Z:/tmp/tmp.RYyft9kBZb/firebase/app/client/unity/proxy/FirebaseAppUtils.cs:33) Firebase.Platform.FirebaseHandler:Update () (在 Z:/tmp/tmp.AqqnQIVt80/firebase/app/client/unity/src/Unity/FirebaseHandler.cs:208) Firebase.Platform.FirebaseMonoBehaviour:Update ()(在 Z:/tmp/tmp.AqqnQIVt80/firebase/app/client/unity/src/Unity/FirebaseMonoBehaviour.cs:45)

【问题讨论】:

  • 您可以编辑您的问题以显示无效的代码吗?安全规则只有在被代码执行后才会变得活跃(并且有意义)。
  • 我刚刚做了!谢谢:)

标签: c# unity3d firebase-realtime-database firebase-security


【解决方案1】:

您的代码正在尝试读取/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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 2020-08-08
    相关资源
    最近更新 更多