Client and server in depth · Lesson 1/4 · 10 min
Secure events: don't trust the client
Any player can fire your network events with whatever data they want. Learn to validate them.
A RegisterNetEvent is an open door: any player can fire it from their client with whatever arguments they please. If you don't validate, you're handing out cheats. In QBCore this is exactly as dangerous as in ESX.
The typical mistake (vulnerable)
-- ❌ BAD: trusts the amount and price sent by the client
RegisterNetEvent('tienda:server:vender', function(cantidad, precio)
local Player = QBCore.Functions.GetPlayer(source)
Player.Functions.AddMoney('cash', cantidad * precio) -- infinite money
end)Vulnerable
Here a cheater sends cantidad=99999 and precio=99999 and gets rich. The price and the logic must NEVER come from the client.
The secure version
RegisterNetEvent('tienda:server:vender', function(itemName, cantidad)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
-- 1) validate types and ranges
cantidad = tonumber(cantidad)
if not cantidad or cantidad < 1 or cantidad > 100 then return end
-- 2) the PRICE is decided by the server, not the client
local precio = Config.Precios[itemName]
if not precio then return end
-- 3) check that the player ACTUALLY HAS what they claim to sell
local item = Player.Functions.GetItemByName(itemName)
if not item or item.amount < cantidad then return end
Player.Functions.RemoveItem(itemName, cantidad)
Player.Functions.AddMoney('cash', precio * cantidad, 'venta-' .. itemName)
end)Full validation
- Validate the type and range of each argument (tonumber, limits).
- Prices, rewards and logic come from Config or DB on the server, never from the client.
- Check that the player has/can do what they ask (GetItemByName, money, job, distance).
Practice what you learned
0/3¿Por qué es peligroso un RegisterNetEvent que se fía de los datos del cliente?
Este evento de venta confía en el precio que manda el cliente (dinero infinito). Arréglalo: el precio debe salir de Config en el servidor, no de los argumentos.
Este código tiene un fallo:
RegisterNetEvent('tienda:server:vender', function(cantidad, precio) local Player = QBCore.Functions.GetPlayer(source) Player.Functions.AddMoney('cash', cantidad * precio)end)Reescríbelo corregido:
Pista
Quita 'precio' de los argumentos, recibe itemName, y léelo con Config.Precios[itemName] dentro del servidor.
Completa la primera línea del cuerpo del evento: guarda el source y obtén el Player, comprobando que existe.
RegisterNetEvent('tienda:server:vender', function(itemName, cantidad) local src = source local Player = QBCore.Functions.GetPlayer(src) if not then return endend)Pista
El jugador puede no estar cargado; el guard corta la ejecución si GetPlayer devolvió nil.
Challenge: code it yourself
Take an event that gives an item to the player and harden it: validate the amount (1-10) and that the item is in a list of allowed Config items.
Write it yourself in your editor (VS Code) and test it on your server. You learn here by doing it, not by copying.
See hint
tonumber + check range + Config.ItemsPermitidos[item] before AddItem.
Escribe aquí tu solución:
