Jak wiadomo formularz logowania można zrobić na dwa sposoby:
Pierwszy z użyciem (zbudowanego formularza w Symfony) oraz drugi (tradycyjny formularz)
1. Sposób: (ten działa bez problemu)
plik login.html.twig
<form method="post" class="form">
<div class="form-group">
<label for="login">Login:</label>
<input type="text" id="login" name="login" placeholder="Login" class="form-control" value="{{ last_username }}"/>
</div>
<div class="form-group">
<label for="password">Hasło:</label>
<input type="password" id="password" name="password" placeholder="Hasło" class="form-control"/>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="_remember_me"> Zapamiętaj mnie
</label>
</div>
<input type="hidden" name="_csrf_token" value="{{csrf_token('authenticate')}}"/>
<div class="form-group">
<button type="submit" class="btn btn-success">Logowanie</button>
</div>
</form>
-SecurityController
/**
* @Route("/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils)
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('home/login.html.twig', [
'last_username'=>$lastUsername,
'error' => $error,
'tytul'=>'Logowanie'
]);
}
-LoginFormAuthenticator
<?php
namespace App\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use App\Repository\UserRepository;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
use TargetPathTrait;
private $userRepository;
private $router;
private $csrfTokenManager;
private $passwordEncoder;
public function __construct(UserRepository $userRepository, RouterInterface $router, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder)
{
$this->userRepository = $userRepository;
$this->router = $router;
$this->csrfTokenManager = $csrfTokenManager;
$this->passwordEncoder = $passwordEncoder;
}
public function supports(Request $request)
{
return $request->attributes->get('_route') === 'app_login' && $request->isMethod('POST');
}
public function getCredentials(Request $request)
{
$credentials = [
'login'=>$request->request->get('login'),
'password'=>$request->request->get('password'),
'csrf_token'=>$request->request->get('_csrf_token')
];
$request->getSession()->set(Security::LAST_USERNAME,$credentials['login']);
return $credentials;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if(!$this->csrfTokenManager->isTokenValid($token))
{
throw new InvalidCsrfTokenException();
}
return $this->userRepository->findOneBy(['login' => $credentials['login']]);
}
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);
}
return new RedirectResponse($this->router->generate('home'));
}
protected function getLoginUrl()
{
return $this->router->generate('app_login');
}
}
2. Sposób (bład: Invalid CSRF token, albo Username could not be found (jak nie korzystam z CSRF)
-login.html.twig
{% if error %}
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
<h2>Logowanie</h2>
{{ form_start(LoginForm,{'method':'POST'}) }}
{{ form_row(LoginForm.login) }}
{{ form_row(LoginForm.password) }}
{{ form_end(LoginForm) }}
-LoginFormType
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use App\Entity\User;
class LoginFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('login',TextType::class,
['label' => 'Twój Login',
'attr'=>['placeholder'=>'Podaj Login...'],
'help' => 'Podaj swój login',
'disabled'=>false,
'required'=>false])
->add('password',PasswordType::class, [
'label' => 'Twoje Hasło',
'attr'=>['placeholder'=>'Podaj Hasło...'],
'required'=>false])
->add('save',SubmitType::class, [
'label' => 'Zaloguj']);
}
}
-SecurityController
/**
* @Route("/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils)
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
$form=$this->createForm(LoginFormType::class, [
'login'=> $lastUsername
]);
return $this->render('home/login.html.twig', [
'LoginForm' => $form->createView(),
'error' => $error
]);
}
oraz
-LoginFormAuthenticator
<?php
namespace App\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use App\Repository\UserRepository;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
use TargetPathTrait;
private $userRepository;
private $router;
private $csrfTokenManager;
private $passwordEncoder;
public function __construct(UserRepository $userRepository, RouterInterface $router, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder)
{
$this->userRepository = $userRepository;
$this->router = $router;
$this->csrfTokenManager = $csrfTokenManager;
$this->passwordEncoder = $passwordEncoder;
}
public function supports(Request $request)
{
return $request->attributes->get('_route') === 'app_login' && $request->isMethod('POST');
}
public function getCredentials(Request $request)
{
$credentials = [
'login'=>$request->request->get('login'),
'password'=>$request->request->get('password'),
'_token'=>$request->request->get('_token')
];
$request->getSession()->set(Security::LAST_USERNAME,$credentials['login']);
return $credentials;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$token = new CsrfToken('authenticate', $credentials['_token']);
if(!$this->csrfTokenManager->isTokenValid($token))
{
throw new InvalidCsrfTokenException();
}
return $this->userRepository->findOneBy(['login' => $credentials['login']]);
}
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);
}
return new RedirectResponse($this->router->generate('home'));
}
protected function getLoginUrl()
{
return $this->router->generate('app_login');
}
}
Gdzie mogłem popełnić bład.. bo siedzę nad tym szukam i nic.
Wiem, że mógłbym pozostać przy tradycyjnym formularzu,ale do nauki chcę poznać obie metody ;)