games / fivem
Commandes & permissions : RegisterCommand, ACE
Explication
Ce que vous allez apprendre
- Créer une commande avec
RegisterCommandet lire ses arguments - Comprendre le principe des ACE (Access Control Entries) : groupes, permissions, identifiants
- Restreindre une commande sensible avec le flag
restricteddeRegisterCommand - Vérifier une permission manuellement dans le code avec
IsPlayerAceAllowed - Journaliser les tentatives refusées pour repérer les abus
Dans quel contexte ?
Un serveur RP doit permettre à ses administrateurs d'exécuter des commandes comme /kick ou /givemoney, tout en interdisant absolument ces mêmes commandes à un joueur ordinaire. Sans système de permissions structuré, chaque développeur finirait par réinventer sa propre vérification, souvent incomplète — les ACE de FiveM offrent un mécanisme standard, éprouvé, pour éviter ce problème.
| Élément | Rôle |
|---|---|
add_ace group.admin command.kick allow | Attribue une permission à un groupe |
add_principal identifier.license:... group.admin | Ajoute un joueur à un groupe |
RegisterCommand(..., true) | Restreint la commande aux joueurs autorisés par ACE |
Piège fréquent
Vérifier une permission uniquement côté client (par exemple cacher un bouton "Kick" dans une UI) ne protège rien : un joueur peut toujours déclencher directement l'event ou la commande serveur correspondante. La vérification de permission doit toujours avoir lieu côté serveur.
Un point d'entrée simple, mais sensible
Une commande tapée dans le chat ou la console (/tp, /kick) est souvent la façon la plus rapide de déclencher une action côté serveur. Mais certaines de ces actions — bannir un joueur, donner de l'argent — ne doivent évidemment pas être accessibles à tout le monde. FiveM fournit un système de permissions intégré pour encadrer cela, plutôt que de laisser chaque développeur réinventer sa propre solution de vérification.
ACE : comprendre le principe avant la syntaxe
ACE (Access Control Entries) fonctionne sur un principe simple, hérité du monde des systèmes d'exploitation : on définit des groupes (comme "admin"), on leur attribue des permissions précises (comme le droit d'utiliser la commande kick), puis on ajoute des joueurs à ces groupes en les identifiant par un identifiant unique et stable (comme leur licence Rockstar). Un joueur hérite alors automatiquement de toutes les permissions de tous les groupes auxquels il appartient.
Le flag "restricted" de RegisterCommand
Le deuxième argument de RegisterCommand (true ou false) indique si FiveM doit lui-même vérifier automatiquement la permission ACE correspondante avant même d'exécuter le code de la commande. Avec true, un joueur sans la permission ne verra même pas son code s'exécuter — la vérification a lieu en amont, de façon transparente.
Pourquoi vérifier manuellement, parfois
Le flag ACE natif reste binaire (autorisé ou non). Pour des logiques plus fines (par exemple, autoriser une action seulement à certaines heures, ou avec des conditions supplémentaires), on peut appeler IsPlayerAceAllowed directement dans le code, en combinant la vérification ACE avec sa propre logique métier.
Le réflexe à prendre : logger les refus
Enregistrer chaque tentative refusée par manque de permission (comme montré avec print('[SECURITY] ...')) donne une trace précieuse pour repérer des joueurs qui testent délibérément les limites du système — une pratique reprise et approfondie dans la leçon sur la sécurité.
Commandes & code
Commandes & permissions
Les commandes chat/console sont un point d'entrée courant pour les fonctionnalités admin ou joueur.
-- Commande simple accessible à tous
RegisterCommand('tp', function(source, args, rawCommand)
local src = source
if src == 0 then return end -- 0 = console serveur, pas un joueur en jeu
local x, y, z = tonumber(args[1]), tonumber(args[2]), tonumber(args[3])
if not x or not y or not z then
TriggerClientEvent('chat:addMessage', src, { args = { 'Usage: /tp x y z' } })
return
end
local ped = GetPlayerPed(src)
SetEntityCoords(ped, x, y, z, false, false, false, true)
end, false) -- false = commande NON restreinte par ACE-- Commande sensible, restreinte par permission ACE
RegisterCommand('kick', function(source, args)
local target = tonumber(args[1])
if target then
DropPlayer(target, 'Kick administrateur')
end
end, true) -- true = restreint : nécessite une permission ACE pour être exécutée; server.cfg : déclaration des groupes et permissions ACE
add_ace group.admin command.kick allow
add_ace group.admin command.givemoney allow
add_principal identifier.license:7c9c0e4c9f3a... group.admin-- Vérification manuelle de permission dans le code (ex: hors commande)
local function IsPlayerAdmin(source)
return IsPlayerAceAllowed(source, 'command.kick')
end
RegisterCommand('givemoney', function(source, args)
if not IsPlayerAdmin(source) then
print(('[SECURITY] %s a tenté /givemoney sans permission'):format(source))
return
end
local target = tonumber(args[1])
local amount = tonumber(args[2])
if not target or not amount then return end
AddMoneyToPlayer(target, amount)
end, false) -- restriction gérée manuellement plutôt que par le flag ACE natif| Élément | Rôle |
|---|---|
add_ace | attribue une permission à un groupe |
add_principal | ajoute un joueur (par identifiant) à un groupe |
RegisterCommand(..., true) | restreint la commande aux joueurs ayant la permission ACE |
IsPlayerAceAllowed | vérification manuelle d'une permission dans le code Lua |
Résumé
- Ne jamais faire confiance à une vérification de permission faite côté client.
- Le flag
restricteddeRegisterCommands'appuie directement sur le système ACE deserver.cfg. - Logger les tentatives refusées aide à détecter les abus/exploits en production.
Exercices pratiques
Mission : le bouton admin qui ne protège rien
Objectif : Corriger une commande sensible protégée uniquement par une interface, et la sécuriser avec ACE et logging.
Contexte
Le serveur affiche un bouton "Donner de l'argent" uniquement dans l'interface des joueurs marqués admin côté client (if isAdminUI then showButton() end). La commande serveur réelle, elle, ressemble à :
RegisterCommand('givemoney', function(source, args)
AddMoneyToPlayer(tonumber(args[1]), tonumber(args[2]))
end, false)Un joueur non-admin a découvert qu'il pouvait taper /givemoney directement dans le chat, sans passer par aucun bouton, et se créditer de l'argent à volonté.