Il est possible avec Symfony2 d’authentifier l’utilisateur LDAP.
Pour cela il faut créer une première classe UserProvider
qui sera le fournisseur d’utilisateur, et une seconde classe User
qui sera notre utilisateur.
Cette article détaillé en explique le fonctionnement : http://symfony.com/fr/doc/current/cookbook/security/custom_provider.html
Tout d’abord, on va renseigner dans le fichier app/config/security.yml
la façon dont on va authentifié l’utilisateur.
security:
providers:
ldap:
id: user_provider
firewalls:
secured_area:
pattern: ^/
remote_user:
provider: ldap
On va retrouver la clef « user_provider » dans notre fichier de déclaration des services app/config/services.yml
services:
ad:
class: AppBundleUtilsAd
arguments: ["%ad_host%", "%ad_user%", "%ad_password%"]
user_provider:
class: AppBundleSecurityUserProvider
calls:
- [setAd, ["@ad"]]
Le service « ad » est une classe qui me permet d’aller chercher les informations utilisateur dans l’Active Directory (nom, prénom, description etc.), c’est pourquoi je l’injecte dans ma classe UserProvider
.
Voici le contenu des classes UserProvider
et User
:
namespace AppBundle\Security;
use AppBundle\Utils\Ad;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
class UserProvider implements UserProviderInterface
{
private $ad;
/**
* @param string $username
* @return UserInterface
* @throws UsernameNotFoundException
*/
public function loadUserByUsername($username)
{
if ($userAd = $this->getAd()->getUserByLogin($username)) {
return new User($userAd->samaccountname, $userAd);
}
throw new UsernameNotFoundException('Utilisateur "' . $username . '" introuvable');
}
/**
* @param UserInterface $user
* @return UserInterface
* @throws UnsupportedUserException
*/
public function refreshUser(UserInterface $user)
{
if (!$user instanceof User) {
throw new UnsupportedUserException('Instance "' . get_class($user) . '" non supportée');
}
return $this->loadUserByUsername($user->getUsername());
}
/**
* @param string $class
* @return bool
*/
public function supportsClass($class)
{
return $class === 'AppBundle\Security\User';
}
/**
* @param Ad $ad
* @return void
*/
public function setAd(Ad $ad)
{
$this->ad = $ad;
}
/**
* @return Ad $ad
*/
public function getAd()
{
return $this->ad;
}
}
namespace AppBundle\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Role\Role;
use AppBundle\Utils\UserAd;
class User implements UserInterface
{
private $username;
private $password;
private $roles = array();
private $nom;
private $prenom;
private $description;
/**
* @param string $username
* @param UserAd $userAd
* @return User
*/
public function __construct($username, UserAd $userAd)
{
$this->username = $username;
$this->nom = $userAd->sn;
$this->prenom = $userAd->givenname;
$this->description = $userAd->description;
// établit les rôles
$roles = array('ROLE_USER');
if ($this->getUsername() === 'jdoe') {
$roles[] = 'ROLE_SUPER_ADMIN';
}
$this->setRoles($roles);
}
/**
* @return string
*/
public function getUsername()
{
return $this->username;
}
/**
* @return string
*/
public function getPassword()
{
return $this->password;
}
/**
* @return Role[] The user roles
*/
public function getRoles()
{
$roles = $this->roles;
if (empty($roles)) {
$roles[] = 'ROLE_USER';
}
return array_unique($roles);
}
/**
* @param array
* @return void
*/
public function setRoles(array $roles)
{
$this->roles = $roles;
}
/**
* @return void
*/
public function getSalt()
{
return;
}
/**
* @return void
*/
public function eraseCredentials()
{
}
/**
* @return string
*/
public function getNom()
{
return $this->nom;
}
/**
* @return string
*/
public function getPrenom()
{
return $this->prenom;
}
/**
* @return string
*/
public function getDescription()
{
return $this->description;
}
}
Ces deux classes doivent impérativement définir les méthodes des interfaces UserProviderInterface
et User
.
Cet exemple est à adapté selon votre système LDAP.
Le fichier de log access.log
d’Apache affichera le login AD de la personne qui lance l’appel HTTP, cela peut vous permettre d’isoler ce champ dans un dashboard Kibana.