X

N’utilisez pas $request->all() : ce n’est pas sécurisé


Assez souvent, je vois des développeurs Laravel utiliser $request->all() dans les méthodes de contrôleur. C’est peut-être un problème de sécurité, laissez-moi vous montrer pourquoi.


Pourquoi $request->all() n’est pas sécurisé

Imaginons que vous ayez un formulaire d’inscription standard :

Ce formulaire est soumis à cette méthode de contrôleur :

public function store(StoreUserRequest $request) {

User::create($request->all());

 

return redirect()->route('dashboard');

}

Nous utilisons une classe Form Request avec validation, donc cela ne semble pas dangereux, n’est-ce pas ? Il devrait enregistrer le nom, l’e-mail et le mot de passe, n’est-ce pas ?

Avis: Je sais que le mot de passe doit être crypté, mais dans cet article, supposons que le cryptage est effectué ailleurs, comme dans Observer ou Mutator.

Maintenant, regardons le $fillable tableau dans le modèle User.

class User extends Authenticatable

{

protected $fillable = [

'name',

'email',

'password',

'is_admin',

];

Regarde ça is_admin colonne? Il est utilisé pour attribuer le rôle d’administrateur, et ce champ ne doit être rempli que par d’autres administrateurs, sous une autre forme que l’inscription, dans un panneau d’administration séparé.

Mais que se passe-t-il si j’essaie d’appeler cet enregistrement à soumettre en ajoutant un hidden champ appelé is_admindirectement depuis mon navigateur, comme les outils de développement Chrome, en cliquant sur Inspecter ?

Devinez quoi : le is_admin sera enregistré avec succès, et je réussirai à m’enregistrer en tant qu’administrateur, sans l’autorisation de personne.

Donc, pour “pirater” le système, tout ce dont j’aurais besoin est de deviner les champs non visuels de la base de données : il peut s’appeler is_adminc’est possible role_idjuste role, ou quoi que ce soit d’autre. Pas si difficile d’écrire un script pour automatiser l’essai de toutes les options possibles.

Cela se produit parce que $request->all() ne filtre ni ne valide rien, c’est juste littéralement all().

Alors, que faire à la place ?


Option 1. Demande de formulaire et validé()

Si vous utilisez la classe Form Request pour la validation, vous avez la rules() méthode ici:

class StoreUserRequest extends FormRequest

{

public function rules()

{

return [

'name' => ['required', 'string', 'max:255'],

'email' => ['required', 'email', 'string', 'max:255'],

'password' => ['nullable', 'string', 'confirmed', 'min:8'],

];

}

}

Ensuite, dans le contrôleur, vous devez utiliser la requête filtré après cette validation. Pour cela, il suffit de remplacer $request->all() avec $request->validated().

public function store(StoreUserRequest $request) {

User::create($request->validated());

 

return redirect()->route('dashboard');

}

Ainsi, il ne remplira que les champs qui sont présents dans le rules() méthode.

Gardez à l’esprit que dans ce cas, vous devez ajouter tous les champs nécessaires dans le rules() tableau, même s’il ne nécessite pas de validation spécifique, ajoutez-les simplement comme nullable ou string.


Option 2. $request->only()

Bien sûr, une autre option consiste à spécifier les champs exacts à utiliser. L’une des options consiste à utiliser $request->only():

public function store(StoreUserRequest $request) {

User::create($request->only('name', 'email', 'password'));

 

return redirect()->route('dashboard');

}


Option 3. Champ par champ

Enfin, la bonne vieille méthode de spécification champ par champ. Le code semble plus long, mais peut-être plus lisible, avec moins d’informations “cachées”.

public function store(StoreUserRequest $request) {

User::create([

'name' => $request->name,

'email' => $request->email,

'password' => $request->password,

]);

 

return redirect()->route('dashboard');

}


Les trois options ci-dessus sont valables, c’est juste votre préférence personnelle, qui peut également dépendre de la forme ou de la situation exacte. L’essentiel est de ne pas utiliser $request->all()oubliez simplement l’existence de cette méthode, pour votre sécurité.