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:
le Provider:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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); } } }
Ma class user
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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;} }
mon user provider:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 usertoken:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 service.yml de mon bundle:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 security_factories.yml:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 routing.yml:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 services: security.authentication.factory.ADM: class: ADManager\AuthentificationBundle\Factory\AuthenticationFactory tags: - { name: security.listener.factory }
le security.yml de app/config:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
les routes sont bien sure déclarées tout comme le bundle.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 }
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:
Je précise aussi que dans mon services.yml, netbeans me signal ceci à la ligne
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
"ScannerException while scanning for the next token we had this found character @(64) that cannot start any token"
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 ADM.security.authentication.listener: class: ADManager\AuthentificationBundle\Controller\AuthenticationListener arguments: [@security.context, @security.authentication.manager]
voilà j'espère avoir donner assez d'info, j'espère que quelqu'un pourra m'aiguiller
merci d'avance
Partager