dzień dobry,
postanowiłem pobawić się z integracją symfony do bazy, która jest już stowrzona, ma swoja strukture, klucze itd.
Utworzyłem sobie encje za pomocą tego narzedzia:
php bin/console doctrine:mapping:port "App\Entity" annotation --path=src/Entity
Wszystko jest w porządku, udało mi się zrobić rejestracje i inne bajerki.
Zatrzymałem się jednak na logowaniu.
Co prawda po kilku szpachlach i kombinacjach udało mi się to zrobić ale:
- Musiałem dodać nowe pole do tabeli, w której trzymam użytkowników.
- Dodać nowy własny encoder sha1 - takie kodowanie wymagane jest przez aplikacje używającą bazy.
Mój encoder wygląda tak:
<?php
namespace App\Security;
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
class Sha1PasswordEncoder implements PasswordEncoderInterface
{
/**
* @inheritDoc
*/
public function encodePassword(string $raw, ?string $salt)
{
return sha1($raw);
}
/**
* @inheritDoc
*/
public function isPasswordValid(string $encoded, string $raw, ?string $salt)
{
return sha1($raw) == $encoded;
}
/**
* @inheritDoc
*/
public function needsRehash(string $encoded): bool
{
// TODO: Implement needsRehash() method.
}
}
Natomiast to jest mój authentykator:
<?php
namespace App\Security;
use App\Entity\Accounts;
use App\Repository\AccountsRepository;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
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\AbstractGuardAuthenticator;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginAuthenticator extends AbstractFormLoginAuthenticator
{
use TargetPathTrait;
/**
* @var AccountsRepository
*/
private $accountsRepository;
/**
* @var CsrfTokenManagerInterface
*/
private $csrfTokenManager;
/**
* @var Sha1PasswordEncoder
*/
private $passwordEncoder;
/**
* @var RouterInterface
*/
private $router;
public function __construct(AccountsRepository $accountsRepository, CsrfTokenManagerInterface $csrfTokenManager, Sha1PasswordEncoder $passwordEncoder, RouterInterface $router)
{
$this->accountsRepository = $accountsRepository;
$this->csrfTokenManager = $csrfTokenManager;
$this->passwordEncoder = $passwordEncoder;
$this->router = $router;
}
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->accountsRepository->findOneBy([
'name' => $credentials['login'],
]);
}
public function checkCredentials($credentials, UserInterface $user)
{
return $this->passwordEncoder->isPasswordValid(
$this->passwordEncoder->encodePassword($credentials['password'], null),
$credentials['password'],
null
);
}
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('app_homepage'));
}
public function supportsRememberMe()
{
return false;
}
protected function getLoginUrl()
{
return $this->router->generate('app_login');
}
}
A tu kontroler:
/**
* @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('security/login.html.twig', [
'last_username' => $lastUsername,
'error' => $error,
]);
}
Wszystko działa poprawnie, użytkownik jest logowany, toolbar pokazuje poprawną autentykację.
Jednakże, moje pytanie brzmi. Co mogę zrobić aby pole roles wywalić do osobnej tabeli? Niestety koliduje ono z kodem gry, który wykorzystuje tą baze. Dodatkowo chciałbym się dowiedzieć czy wszystko wykonałem poprawnie i zgodnie ze sztuką.
Pozdrawiam