Création d'un bundle d'authentification
Bonjour,
Dans l'optique de créer mon propre système d'authentification sur un AD (ldap), j'essaie de comprendre le mécanisme complet mis en œuvre sous symfony.
J'essaie pour le moment de créer le mécanisme de bas d'authentification sans aller cherche dans une quelconque base ou autre, l'idée est que le système me renvoie l'autorisation.
J'ai donc suivi de nombreux tuto/forum etc... Je me base maintenant essentiellement sur ça:
http://symfony.com/doc/current/cookbook/security/custom_provider.html
Mon projet est construit dans src/ADManager et j'ai un Bundle qui se nomme AuthenticationBundle
Voici toutes mes class et fichiers divers:
le Listener:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
namespace ADManager\AuthentificationBundle\Controller;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use ADManager\AuthentificationBundle\Controller\UserToken;
use AADManager\AuthentificationBundle\Controller\AuthenticationProvider;
class AuthenticationListener implements ListenerInterface
{
private $context;
private $authManager;
public function __construct(SecurityContextInterface $context, AuthenticationManagerInterface $authManager)
{
$this->context = $context;
$this->authManager = $authManager;
}
/**
* Handles access authorization.
*
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(GetResponseEvent $event)
{
$token = $this->context->getToken();
if (null === $token)
{throw new AuthenticationCredentialsNotFoundException('A Token was not found in the SecurityContext.');}
//$request = $event->getRequest();
if (!$token->isAuthenticated())
{
$token = $this->authManager->authenticate($token);
return $this->context->setToken($token);
}
else
{
return $this->context->setToken($token);
}
}
} |
le Provider:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
namespace ADManager\AuthentificationBundle\Controller;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
use ADManager\AuthentificationBundle\Controller\UserToken;
class AuthenticationProvider implements AuthenticationProviderInterface
{
private $userProvider;
public function __construct(UserProviderInterface $userProvider)
{
$this->userProvider = $userProvider;
}
public function authenticate(TokenInterface $token)
{
if(true)
{
$TokenAuthentifie = new UserToken("admin", "admin", "ADM", array('ROLE_ADMIN'));
return $TokenAuthentifie;
}
throw new AuthenticationException('The WSSE authentication failed.');
}
public function supports(TokenInterface $token)
{return true;}
} |
Ma class user
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
namespace ADM\AuthenticationBundle\Controller;
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface
{
protected $username;
protected $password;
protected $roles;
protected $groups;
protected $salt;
public function __construct($username, $password, $salt, array $roles)
{
$this->username = $username;
$this->password = $password;
$this->salt = $salt;
$this->roles = $roles;
//$this->groups = array();
}
public function equals(UserInterface $user)
{
if (!$user instanceof WebserviceUser) {return false;}
if ($this->password !== $user->getPassword()) {return false;}
if ($this->getSalt() !== $user->getSalt()) {return false;}
if ($this->username !== $user->getUsername()) {return false;}
return true;
}
public function eraseCredentials()
{$this->password = null;}
public function setPassword($password)
{$this->password = $password;}
public function getPassword()
{return $this->password;}
public function setRoles($roles)
{$this->roles = $roles;}
public function getRoles()
{return $this->roles;}
public function setSalt($salt)
{$this->salt = $salt;}
public function getSalt()
{return $this->salt;}
public function setUsername($username)
{$this->username = $username;}
public function getUsername()
{return $this->username;}
} |
mon user provider:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
namespace ADM\AuthenticationBundle\Controller;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use ADM\AuthenticationBundle\Controller\User;
class UserProvider implements UserProviderInterface
{
private $UserPWD;
/**
* Le password de l'utilisateur doit être au préalable enregistré via la fonction setUserPWD($userpwd)
* @param type $username
* @return \AdLdap\UserBundle\Security\User
* @throws UsernameNotFoundException
*/
public function loadUserByUsername($username)
{
// Instanciation du LDAP
//$ldap = $this->container->get('adldap_adldap');
//$Liste_Roles = array();
//if($ldap->authenticate($username, $UserPWD, false))
// {
// $Liste_Roles_Group = $this->container->getParameter('roles_groupes');
// foreach($Liste_Roles_Group as $roles => $group)
// {
// if($ldap->user->inGroup($username, $group, NULL, false))
// {$Liste_Roles[] = $roles;}
// }
// return new User($username, $UserPWD, '', $roles);
// }
//else
// {throw new UsernameNotFoundException(sprintf('l\'utilisateur "%s" n\'existe pas.', $username));}
return new User("admin", "admin", '', 'ROLE_ADMIN');
}
public function refreshUser(UserInterface $user)
{
if (!$user instanceof User)
{throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));}
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{return $class === 'AdLdap\UserBundle\Security\User';}
public function setUserPWD($userpwd)
{$UserPWD = $userpwd;}
} |
mon usertoken:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
namespace ADManager\AuthentificationBundle\Controller;
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class AuthenticationToken extends AbstractToken implements TokenInterface
{
private $credentials;
private $providerKey;
/**
* Constructor.
*
* @param string $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method.
* @param string $credentials This usually is the password of the user
* @param string $providerKey The provider key
* @param array $roles An array of roles
*
* @throws \InvalidArgumentException
*/
public function __construct($user, $credentials, $providerKey, array $roles = array())
{
parent::__construct($roles);
if (empty($providerKey))
{throw new \InvalidArgumentException('$providerKey must not be empty.');}
$this->setUser($user);
$this->credentials = $credentials;
$this->providerKey = $providerKey;
parent::setAuthenticated(count($roles) > 0);
}
/**
* {@inheritdoc}
*/
public function setAuthenticated($isAuthenticated)
{
if ($isAuthenticated)
{throw new \LogicException('Cannot set this token to trusted after instantiation.');}
parent::setAuthenticated(false);
}
public function getCredentials()
{return $this->credentials;}
public function getProviderKey()
{return $this->providerKey;}
/**
* {@inheritdoc}
*/
public function eraseCredentials()
{
parent::eraseCredentials();
$this->credentials = null;
}
public function serialize()
{return serialize(array($this->credentials, $this->providerKey, parent::serialize()));}
public function unserialize($str)
{
list($this->credentials, $this->providerKey, $parentStr) = unserialize($str);
parent::unserialize($parentStr);
}
} |
mon service.yml de mon bundle:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
parameters:
# ad_manager_authentification.example.class: ADManager\AuthentificationBundle\Example
services:
ADM.security.authentication.provider:
class: ADManager\AuthentificationBundle\Controller\AuthenticationProvider
ADM.security.user.provider:
class: ADManager\AuthentificationBundle\Controller\UserProvider
ADM.security.authentication.listener:
class: ADManager\AuthentificationBundle\Controller\AuthenticationListener
arguments: [@security.context, @security.authentication.manager]
security.authentication.factory.ADM:
class: ADManager\AuthentificationBundle\Factory\AuthenticationFactory
tags:
- { name: security.listener.factory } |
mon security_factories.yml:
Code:
1 2 3 4 5 6
|
services:
security.authentication.factory.ADM:
class: ADManager\AuthentificationBundle\Factory\AuthenticationFactory
tags:
- { name: security.listener.factory } |
mon routing.yml:
Code:
1 2 3 4 5 6 7 8 9 10
|
_security_login:
pattern: /login
defaults: { _controller: ADMAuthenticationBundle:Authentication:login }
_security_check:
pattern: /login_check
_security_logout:
pattern: /logout |
le security.yml de app/config:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
factories:
- "%kernel.root_dir%/../src/ADManager/AuthentificationBundle/Resources/config/security_factories.yml"
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
in_memory:
users:
user: { password: userpass, roles: [ 'ROLE_USER' ] }
admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
ADM_provider:
id: ADM.security.user.provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/demo/secured/login$
security: false
ADM_provider:
pattern: ^/DSI/.*
provider: ADM.provider
form_login:
check_path: _security_check
login_path: _security_login
logout:
path: _security_logout
target: /DSI/index #Mettre ici la route vers votre page d'accueil
#security: true
ADM: true
anonymous: false
access_control:
#- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
#- { path: ^/_internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 } |
les routes sont bien sure déclarées tout comme le bundle.
Je vous passe les vues..
J'ai déjà réussi à débuguer pas mal d'erreur mais la je bloque...
lorsque j'essaie mon url voici le message d'erreur:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
Whoops, looks like something went wrong.
1/1 OutOfBoundsException: The index "0" is not in the range [0, -1].
in /MOUNT/WWW/Dsi-Symfony/vendor/symfony/src/Symfony/Component/DependencyInjection/Definition.php line 248
at Definition->replaceArgument() in /MOUNT/WWW/Dsi-Symfony/vendor/symfony/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php line 124
at ResolveDefinitionTemplatesPass->resolveDefinition() in /MOUNT/WWW/Dsi-Symfony/vendor/symfony/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php line 49
at ResolveDefinitionTemplatesPass->process() in /MOUNT/WWW/Dsi-Symfony/vendor/symfony/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php line 119
at Compiler->compile() in /MOUNT/WWW/Dsi-Symfony/vendor/symfony/src/Symfony/Component/DependencyInjection/ContainerBuilder.php line 437
at ContainerBuilder->compile() in /MOUNT/WWW/Dsi-Symfony/app/bootstrap.php.cache line 872
at Kernel->buildContainer() in /MOUNT/WWW/Dsi-Symfony/app/bootstrap.php.cache line 783
at Kernel->initializeContainer() in /MOUNT/WWW/Dsi-Symfony/app/bootstrap.php.cache line 517
at Kernel->boot() in /MOUNT/WWW/Dsi-Symfony/app/bootstrap.php.cache line 548
at Kernel->handle() in /MOUNT/WWW/Dsi-Symfony/web/app_dev.php line 28 |
Je précise aussi que dans mon services.yml, netbeans me signal ceci à la ligne
Code:
1 2 3 4
|
ADM.security.authentication.listener:
class: ADManager\AuthentificationBundle\Controller\AuthenticationListener
arguments: [@security.context, @security.authentication.manager] |
"ScannerException while scanning for the next token we had this found character @(64) that cannot start any token"
voilà j'espère avoir donner assez d'info, j'espère que quelqu'un pourra m'aiguiller :)
merci d'avance