Hello,
Je fais face actuellement à un problème de connexion pour l’accès à mon espace d'administration.
Un message d'erreur " Invalid credentials." apparaît sachant que j'ai actuellement un seul utilisateur en base (username="admin" / pass="password").
Pour information en local le formulaire d'authtification fonctionne, c'est donc suite a la mise en ligne de mon projet que le message est apparu.
Je suppose qu'il y a donc un problème de sécurité. C'est la première fois que je déploie une application en ligne je suis un peu perdu.
User entity
SecurityController
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 <?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Security\Core\User\UserInterface; /** * @ORM\Entity(repositoryClass="App\Repository\UserRepository") */ class User implements UserInterface { /** * @ORM\Id() * @ORM\GeneratedValue() * @ORM\Column(type="integer") */ private $id; /** * @ORM\Column(type="string", length=180, unique=true) */ private $username; /** * @ORM\Column(type="json") */ private $roles = []; /** * @var string The hashed password * @ORM\Column(type="string") */ private $password; public function getId(): ?int { return $this->id; } /** * A visual identifier that represents this user. * * @see UserInterface */ public function getUsername(): string { return (string) $this->username; } public function setUsername(string $username): self { $this->username = $username; return $this; } /** * @see UserInterface */ public function getRoles(): array { $roles = $this->roles; // guarantee every user at least has ROLE_USER $roles[] = 'ROLE_USER'; return array_unique($roles); } public function setRoles(array $roles): self { $this->roles = $roles; return $this; } /** * @see UserInterface */ public function getPassword(): string { return (string) $this->password; } public function setPassword(string $password): self { $this->password = $password; return $this; } /** * @see UserInterface */ public function getSalt() { // not needed when using the "bcrypt" algorithm in security.yaml } /** * @see UserInterface */ public function eraseCredentials() { // If you store any temporary, sensitive data on the user, clear it here // $this->plainPassword = null; } }
login form authentification
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 <?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; class SecurityController extends AbstractController { /** * @Route("/login", name="app_login") */ public function login(AuthenticationUtils $authenticationUtils): Response { // get the login error if there is one $error = $authenticationUtils->getLastAuthenticationError(); // last username entered by the user $lastUsername = $authenticationUtils->getLastUsername(); return $this->render('security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error]); } }
security.yaml
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 <?php namespace App\Security; use App\Entity\User; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException; use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException; use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator; use Symfony\Component\Security\Http\Util\TargetPathTrait; class LoginFormAuthenticator extends AbstractFormLoginAuthenticator { use TargetPathTrait; private $entityManager; private $urlGenerator; private $csrfTokenManager; private $passwordEncoder; public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder) { $this->entityManager = $entityManager; $this->urlGenerator = $urlGenerator; $this->csrfTokenManager = $csrfTokenManager; $this->passwordEncoder = $passwordEncoder; } public function supports(Request $request) { return 'app_login' === $request->attributes->get('_route') && $request->isMethod('POST'); } public function getCredentials(Request $request) { $credentials = [ 'username' => $request->request->get('username'), 'password' => $request->request->get('password'), 'csrf_token' => $request->request->get('_csrf_token'), ]; $request->getSession()->set( Security::LAST_USERNAME, $credentials['username'] ); return $credentials; } public function getUser($credentials, UserProviderInterface $userProvider) { $token = new CsrfToken('authenticate', $credentials['csrf_token']); if (!$this->csrfTokenManager->isTokenValid($token)) { throw new InvalidCsrfTokenException(); } $user = $this->entityManager->getRepository(User::class)->findOneBy(['username' => $credentials['username']]); if (!$user) { // fail authentication with a custom error throw new CustomUserMessageAuthenticationException('Username could not be found.'); } return $user; } public function checkCredentials($credentials, UserInterface $user) { return $this->passwordEncoder->isPasswordValid($user, $credentials['password']); } public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) { if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) { return new RedirectResponse($targetPath); } // For example : return new RedirectResponse($this->urlGenerator->generate('some_route')); return new RedirectResponse($this->urlGenerator->generate('admin')); } protected function getLoginUrl() { return $this->urlGenerator->generate('app_login'); } }
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 security: encoders: App\Entity\User: algorithm: argon2i # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers providers: # used to reload user from session & other features (e.g. switch_user) app_user_provider: entity: class: App\Entity\User property: username firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false main: anonymous: true guard: authenticators: - App\Security\LoginFormAuthenticator logout: path: app_logout target: app_login # activate different ways to authenticate # http_basic: true # https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate # form_login: true # https://symfony.com/doc/current/security/form_login_setup.html # Easy way to control access for large sections of your site # Note: Only the *first* access control that matches will be used access_control: - { path: ^/admin, roles: ROLE_ADMIN }
Ma fixture de création d’utilisateur
login vue
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 <?php namespace App\DataFixtures; use App\Entity\User; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; class UserFixtures extends Fixture { private $passwordEncoder; public function __construct(UserPasswordEncoderInterface $passwordEncoder){ $this->passwordEncoder = $passwordEncoder; } public function load(ObjectManager $manager) { $user = new User(); $roles[] = 'ROLE_ADMIN'; $user->setUsername('admin') ->setRoles($roles) ->setPassword($this->passwordEncoder->encodePassword( $user, 'password' )); $manager->persist($user); $manager->flush(); } }
Je vous remercie par avance de votre lecture. Bonne journée
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
72
73
74
75
76
77
78 <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- Favicon --> <link href="/img/brand/favicon.png" rel="icon" type="image/png"> <!-- Fonts --> <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700" rel="stylesheet"> <!-- Icons --> <link href="/vendor/nucleo/css/nucleo.css" rel="stylesheet"> <link href="/vendor/@fortawesome/fontawesome-free/css/all.min.css" rel="stylesheet"> <!-- Argon CSS --> <link type="text/css" href="/css/argon.min.css?v=1.0.0" rel="stylesheet"> <title>Document</title> </head> <body class="bg-default"> <div class="header bg-gradient-primary py-7 py-lg-8"> <div class="container"> <div class="header-body text-center mb-7"> <div class="row justify-content-center"> <div class="col-lg-5 col-md-6"> <h1 class="text-white">Welcome!</h1> <p class="text-lead text-light">Vous êtes sur la page d'authentification des administrateur</p> </div> </div> </div> </div> <div class="separator separator-bottom separator-skew zindex-100"> <svg x="0" y="0" viewBox="0 0 2560 100" preserveAspectRatio="none" version="1.1" xmlns="http://www.w3.org/2000/svg"> <polygon class="fill-default" points="2560 0 2560 100 0 100"></polygon> </svg> </div> </div> <div class="container mt--8 pb-5"> <div class="row justify-content-center"> <div class="col-lg-5 col-md-7"> <div class="card bg-secondary shadow border-0"> <div class="card-body px-lg-5 py-lg-5"> <div class="text-center text-muted mb-4"> <h4>Espace de connexion à l'administration</h4> </div> <form method="post"> {% if error %} <div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div> {% endif %} <div class="form-group mb-3"> <div class="input-group input-group-alternative"> <div class="input-group-prepend"> <span class="input-group-text"><i class="ni ni-single-02"></i></span> </div> <input type="text" value="{{ last_username }}" name="username" id="inputUsername" class="form-control" placeholder="Username" required autofocus> </div> </div> <div class="form-group"> <div class="input-group input-group-alternative"> <div class="input-group-prepend"> <span class="input-group-text"><i class="ni ni-lock-circle-open"></i></span> </div> <input type="password" name="password" id="inputPassword" class="form-control input-group-prepend" placeholder="Password" required> </div> </div> <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}" > <div class="text-center"> <button class="btn btn-primary my-4" type="submit">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </body> </html>
Partager