Un petit service d'emprunt d'identité pour FOSUserBundle (French)

2013-08-20

  symfony    french 

Je vous ai écrit un service qui va vous permettre d'emprunter l'identité d'un autre utilisateur lorsque vous utilisez FOSUserBundle dans vos projets Symfony.

Ainsi, vous pourrez temporairement apparaître sous l'identité d'un autre compte utilisateur, puis, revenir ensuite à votre véritable identité.

Le service

namespace Eko\\MyBundle\\Identity;

use Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken;
use Symfony\\Component\\Security\\Core\\SecurityContextInterface;
use Symfony\\Component\\HttpFoundation\\Session\\SessionInterface;

use FOS\\UserBundle\\Model\\UserInterface;

/**
 * Class Spoofer
 *
 * This service is used to use the identity of another user
 */
class Spoofer
{
    /**
     * @var SessionInterface
     */
    protected $session;

    /**
     * @var SecurityContextInterface
     */
    protected $securityContext;

    /**
     * Constructor
     *
     * @param SessionInterface         $session         Symfony session service
     * @param SecurityContextInterface $securityContext Symfony security context service
     */
    public function __construct(SessionInterface $session, SecurityContextInterface $securityContext)
    {
        $this->session         = $session;
        $this->securityContext = $securityContext;
    }

    /**
     * Spoof the identity of a given user by setting the user in the security context and storing the
     * current administrator user in the session
     *
     * @param UserInterface $user
     */
    public function spoof(UserInterface $user)
    {
        $spoofer = $this->securityContext->getToken()->getUser();
        $this->session->set('spoofer', $spoofer);

        $this->setToken($user);
    }

    /**
     * Stops spoofing an identity and rewinds original administrator identity
     *
     * @throws \\Exception
     */
    public function stop()
    {
        if (!$this->isSpoofing()) {
            throw new \\Exception('There is currently no spoofing');
        }

        $spoofer = $this->session->get('spoofer');
        $this->setToken($spoofer);

        $this->session->set('spoofer', null);
    }

    /**
     * Returns if current user is spoofing an identity
     *
     * @return bool
     */
    public function isSpoofing()
    {
        return $this->session->get('spoofer') ? true : false;
    }

    /**
     * Sets a new token to Symfony security context
     *
     * @param UserInterface $user
     */
    protected function setToken(UserInterface $user)
    {
        $token = new UsernamePasswordToken($user, $user->getPassword(), 'main', $user->getRoles());

        $this->securityContext->setToken($token);
    }
}

Enregistrons également ce service dans le conteneur d'injection de dépendance de Symfony :


<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>

        <service id="eko.mybundle.identity.spoofer" class="Eko\\MyBundle\\Identity\\Spoofer" public="true">
            <argument type="service" id="session" />
            <argument type="service" id="security.context" />
        </service>

    </services>
</container>

Ce service prend donc en argument la session ainsi que le contexte de sécurité de Symfony.

La méthode spoof($user) va vous permettre de prendre l'identité d'un utilisateur et votre réelle identité sera quand à elle temporairement stockée en session.

Lorsque vous souhaiterez récupérer votre identité, appelez simplement la méthode stop().

Cas d'utilisation

Voici un exemple simple ou nous souhaitons emprunter l'identité de l'utilisateur dont l'identifiant est 23, depuis un contrôleur :


$user = $this->getUserManager()->findUserBy(array('id' => 23));
$this->get('eko.mybundle.identity.spoofer')->spoof($user);

Puis, pour revenir à votre identité originale :


$this->get('eko.mybundle.identity.spoofer')->stop();

Have fun.

Comments