Symfony offre une architecture complète et flexible pour gérer les utilisateurs et leurs rôles, en permettant d’authentifier et d’autoriser les accès selon des critères précis.
Les utilisateurs
Interface UserInterface
Tout utilisateur doit implémenter l’interface Symfony\Component\Security\Core\User\UserInterface
, qui garantit la disponibilité des méthodes suivantes :
getUserIdentifier()
: retourne l’identifiant de l’utilisateur (souvent un nom ou email).getRoles()
: retourne un tableau de rôles associés à l’utilisateur.eraseCredentials()
: méthode utilisée pour effacer les informations sensibles, comme des mots de passe temporaires.
Interface PasswordAuthenticatedUserInterface
Si l’authentification repose sur un mot de passe, l’objet utilisateur doit également implémenter cette interface, ajoutant la méthode :
getPassword()
: retourne le mot de passe haché.
Exemple d’entité utilisateur simple
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
#[ORM\Entity]
class Utilisateur implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Column(type: 'integer')]
#[ORM\Id]
#[ORM\GeneratedValue]
private $id;
#[ORM\Column(type: 'string', unique: true)]
private $username;
#[ORM\Column(type: 'string')]
private $password;
public function getUserIdentifier(): string
{
return $this->username;
}
public function getRoles(): array
{
return ['ROLE_USER'];
}
public function getPassword(): ?string
{
return $this->password;
}
public function eraseCredentials(): void
{
// Supprime les informations sensibles
}
}
Fournisseurs d’utilisateurs
Les fournisseurs d’utilisateurs (user providers) permettent de gérer les sources d’utilisateurs.
a. En mémoire
Définissez des utilisateurs statiques directement dans le fichier security.yaml
:
security:
providers:
mes_utilisateurs:
memory:
users:
bob: { password: pa$S, roles: ['ROLE_USER'] }
sarah: { password: 4Dm1nP4$s, roles: ['ROLE_ADMIN'] }
b. En base de données
Pour stocker les utilisateurs dans une base de données :
- Créer une entité utilisateur
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
#[ORM\Entity]
class Utilisateur implements UserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', unique: true)]
private $username;
#[ORM\Column(type: 'string')]
private $password;
public function getUserIdentifier(): string
{
return $this->username;
}
public function getRoles(): array
{
return ['ROLE_USER'];
}
public function getPassword(): ?string
{
return $this->password;
}
public function eraseCredentials(): void {}
}
- Configurer le fournisseur d’utilisateurs
Ajoutez un fournisseur basé sur une entité Doctrine :
security:
providers:
ma_bdd:
entity:
class: App\Entity\Utilisateur
property: username
- Mettre à jour la base de données Créez la table correspondante avec Doctrine :
php bin/console doctrine:schema:update --force
c. Fournisseur personnalisé
Pour des cas spécifiques, implémentez UserProviderInterface
:
<?php
namespace App\Security;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
class CustomUserProvider implements UserProviderInterface
{
public function loadUserByUsername(string $username): UserInterface
{
// Exemple de chargement depuis une source personnalisée
if ($username === 'admin') {
return new CustomUser($username, 'hashedPassword');
}
throw new UsernameNotFoundException("Utilisateur non trouvé");
}
public function refreshUser(UserInterface $user): UserInterface
{
// Implémentation nécessaire
}
public function supportsClass(string $class): bool
{
return $class === CustomUser::class;
}
}
Configurez ce fournisseur comme service et référencez-le dans security.yaml
.
Cryptage des mots de passe
Configurer le hachage des mots de passe
Dans security.yaml
:
security:
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
algorithm: auto
Hacher un mot de passe
Utilisez UserPasswordHasherInterface
pour crypter un mot de passe :
public function index(UserPasswordHasherInterface $passwordHasher)
{
$utilisateur = new Utilisateur();
$motDePasseCrypte = $passwordHasher->hashPassword($utilisateur, 'monMotDePasse');
$utilisateur->setPassword($motDePasseCrypte);
}
Rôles et hiérarchie
Les rôles définissent les permissions associées à un utilisateur.
Définir les rôles
La méthode getRoles()
retourne les rôles d’un utilisateur :
public function getRoles(): array
{
$roles = ['ROLE_USER'];
if ($this->isAdmin) {
$roles[] = 'ROLE_ADMIN';
}
return $roles;
}
Hiérarchie des rôles
Simplifiez la gestion des rôles en définissant une hiérarchie dans security.yaml
:
security:
role_hierarchy:
ROLE_MODERATEUR: ROLE_USER
ROLE_ADMIN: [ROLE_MODERATEUR]
Ainsi, un utilisateur avec ROLE_ADMIN
aura automatiquement les permissions de ROLE_MODERATEUR
et ROLE_USER
.
- Les utilisateurs doivent implémenter
UserInterface
(etPasswordAuthenticatedUserInterface
si un mot de passe est nécessaire). - Les fournisseurs d’utilisateurs gèrent leur source (mémoire, base de données ou personnalisée).
- Protégez les mots de passe avec un cryptage approprié.
- Les rôles et hiérarchies simplifient la gestion des permissions.
Cette architecture offre une flexibilité pour gérer divers besoins d’authentification et d’autorisation.