Formation PUB030 : Laravel, 2019 Les droits (authorization)

41.1 Définir les droits des usagers (ACL : Access Control List)


Laravel met à notre disposition un système sophistiqué de gestion des droits pour les usagers. Et en prime, il est simple à mettre en oeuvre.

Le principe est le suivant :

La gestion des droits est basée sur le modèle de données d'un item, par exemple le modèle Produit. Vous associerez à chacun des modèles les conditions pour qu'un usager authentifié puisse effectuer telle ou telle opération. On appelle ces conditions les politiques de droits (policies).

Avant d'effectuer une opération sur un produit, Laravel vérifiera dans les politiques de droits si l'usager répond aux règles en place.

Si l'usager détient les droits requis, l'opération aura lieu comme prévu. Sinon, une erreur 403 (accès refusé) sera envoyée au navigateur.

Créer le ficher de politiques de droits

Il existe plusieurs façons de définir les droits. La technique des politiques de droits permet de créer du code épuré et bien découpé. 

Le squelette du fichier de politiques peut être créé à l'aide d'une commande artisan.

Ex :

Console Vagrant SSH

php artisan make:policy NomModelePolicy

Ainsi, si on choisit de créer un fichier de politiques de droits pour les produits, le fichier se nommera ProduitPolicy. La commande artisan le placera automatiquement dans le dossier app\Policies.

Voici le squelette de ce fichier :

Fichier ProduitPolicy.php

<?php

 

namespace App\Policies;

 

use App\User;

use Illuminate\Auth\Access\HandlesAuthorization;

 

class ProduitPolicy

{

    use HandlesAuthorization;

 

    /**

     * Create a new policy instance.

     *

     * @return void

     */

    public function __construct()

    {

        //

    }

}

Inscrire le fichier de politiques de droits dans AuthServiceProvider

Pour que ce fichier soit pris en compte, il faut dire à Laravel de faire le lien entre ce fichier et un modèle (dans notre exemple, le modèle Produit). Ceci sera fait dans le fichier app\Providers\AuthServiceProvider.php.

Ex :

Fichier app\Providers\AuthServiceProvider.php

<?php

 

namespace App\Providers;

 

use Illuminate\Support\Facades\Gate;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

 

class AuthServiceProvider extends ServiceProvider

{

    /**

     * The policy mappings for the application.

     *

     * @var array

     */

    protected $policies = [

        'App\Produit' => 'App\Policies\ProduitPolicy',

    ];

 

    /**

     * Register any application authentication / authorization services.

     *

     * @return void

     */

    public function boot()

    {

        $this->registerPolicies();

 

        //

    }

}

Ainsi, lorsqu'on vérifiera les droits pour un objet de type Produit, Laravel saura qu'il doit vérifier dans le fichier ProduitPolicy.

Écrire les règles d'attribution des droits

Les droits seront généralement indiqués dans une méthode qui porte le même nom que la méthode d'action à laquelle ils seront associés.

Cette méthode recevra automatiquement :

  • un objet représentant l'usager;
  • l'item sur lequel on s'apprête à poser une action.
Fichier de politiques de droits (PHP)

/**

* Determine si le ... peut être ... par l'usager.

*

* @param \App\Usager $usager

* @param \App\Modele $objet

* @return bool

*/

public function action(Usager $usager, Modele $objet) : bool

{

    ...

}

Ex :

Fichier ProduitPolicy.php

/**

* Determine si le produit peut être édité par l'usager.

*

* @param \App\Usager $usager

* @param \App\Produit $produit

* @return bool

*/

public function edit(Usager $usager, Produit $produit) : bool

{

    $autorise = false;

 

    // écrire ici le code qui déterminera si l'usager a le droit d'effectuer l'opération sur l'enregistrement

 

    return $autorise;

}

Vérifier les droits

Une fois le mécanisme de vérification des droits en place, on pourra effectuer la vérification.

Il suffit d'appeler la méthode authorize() en lui passant en paramètre le nom de la méthode à utiliser et un objet dont le modèle correspond à ce qui a été associé au fichier de politiques.

Dans notre exemple, puisque le fichier AuthServiceProvider.php associe les politiques de ProduitPolicy au modèle Produit, il faut passer en paramètre un objet de type Produit.

Lors de l'appel de la méthode authorize(), Laravel injectera automatiquement l'objet qui représente l'usager authentifié.

Contrôleur Laravel (PHP)

/**

 * Affiche la page pour éditer un produit.

 *

 * @param Produit $produit

 * @return \Illuminate\View\View

 */

public function edit(Produit $produit) : View

{

    $this->authorize('edit', $produit);   // si la vérification échoue, générera une erreur 403 et le reste de la méthode ne sera pas effectué.

 

    return view('produits.edit', compact('produit'));

}

Attention : si l'usager n'est pas authentifié, authorize() générera toujours une erreur 403 sans même ouvrir le fichier de politiques.

Laravel permet également d'effectuer une vérification des droits à l'aide d'un if, ce qui sera pratique si les droits doivent être vérifiés à l'intérieur d'un algorithme. Ceci sera fait à partir d'un objet représentant un usager (classe User ou autre si vous avez renommé le modèle des usagers dans le fichier config\auth.php).

Fichier quelconque (PHP)

if ($usager->can('edit', $produit)) {

    ...

}

ou :

Fichier quelconque (PHP)

if (Auth::user()->can('edit', $produit)) {

    ...

}

Vérification des droits sans instance du modèle

Lorsqu'il s'agit de modifier ou de supprimer un enregistrement, les droits sont vérifiés à l'aide du paramètre qui représente l'enregistrement concerné (ex : $produit). C'est grâce au type de ce paramètre (ex : Produit) que Laravel sait dans quel fichier de politiques il doit faire ses vérifications.

Mais dans le cas d'un ajout, l'objet à ajouter n'existe pas encore. Alors, comment procéder ?

Laravel a tout prévu.

D'abord, dans le fichier de politiques, la méthode ne recevra qu'un seul paramètre : l'usager.

Ex :

Fichier ProduitPolicy.php

class ProduitPolicy

{

    ...

 

    /**

    * Determine si produit peut être créé par l'usager.

    *

    * @param \App\Usager $usager

    * @return bool

    */

    public function create(Usager $usager) : bool

    {

        $autorise = false;

 

        // écrire ici le code qui déterminera si l'usager a le droit d'effectuer l'opération pour ce modèle

 

        return $autorise;

}

Et dans le contrôleur, c'est le nom de la classe qui sera passé en paramètre afin que Laravel sache où retrouver la politique à utiliser.

Remarquez qu'il est obligatoire à ce moment de spécifier le nom de la méthode du fichier de politiques.

Ex :

Contrôleur Laravel (PHP)

$this->authorize('create', Produit::class);

Vérification de droits qui nécessite plusieurs paramètres

Dans certaines situations, la méthode qui vérifie si l'usager détient les droits requis aura besoin de plusieurs paramètre pour effectuer ses vérifications. Par exemple, dans un système de publication de notes de cours, les usagers pourraient avoir le droit de consulter une formation mais avoir des restrictions sur certaines fiches. Dans cet exemple, une même fiche peut faire partie de plusieurs formations. La méthode devra donc savoir pour quelle formation elle doit faire la vérification.

Dans un tel cas, il est possible de passer plusieurs paramètres à la fonction dans le fichier de politiques. Le premier paramètre sera toujours l'usager et les paramètres suivants seront ceux que le contrôleur passera à la méthode authorize().

Ex :

Fichier xxxPolicy.php

/**

* Determine si la fiche, quand elle fait partie de la formation, peut être affichée par l'usager.

*

* @param \App\Usager $usager

* @param \App\Fiche $fiche

* @param \App\Formation $formation

* @return bool

*/

public function show(Usager $usager, Fiche $fiche, Formation $formation) : bool

{

    ...

}

Lorsqu'une méthode d'action devra effectuer la vérification, il faudra placer les paramètres entre crochets dans l'appel de Authorize :

Contrôleur Laravel (PHP)

$this->authorize('show', [$fiche, $formation]);

Pour plus d'information

« Authorization ». Laravel. https://laravel.com/docs/master/authorization

« ACL (Access Control List) Authorization in Laravel 5.1 ». Matt Stauffer. https://mattstauffer.co/blog/acl-access-control-list-authorization-in-laravel-5-1

« Gates and Policies in Laravel ». Envato Tuts. https://code.tutsplus.com/tutorials/gates-and-policies-in-laravel--cms-29780

▼Publicité

Veuillez noter que le contenu de cette fiche vous est partagé à titre gracieux, au meilleur de mes connaissances et sans aucune garantie.
Merci de partager !
Soumettre