Я работаю с Symfony 4.2,
Я работаю с компонентом безопасности и пытаюсь добавить запомнить меня.
Сначала «Помни меня» работало для меня, но когдаМой пользовательский объект стал настроенным, помните, что я больше не работает,
Мой пользовательский пользователь:
Я подключен к базе данных WordPress, что я не могу внести в нее изменения (Я должен только для чтения), и мне нужно добавить какое-то поле для пользователя, поэтому я должен создать новую таблицу User OneToOne с WpUsers (пользователи WordPress),
Итак, я использую доктрину для создания сущности изсуществующую БД, я не затрагивал эти сущности, я просто создал свой пользовательский объект только для того, чтобы добавить поле ролей в пользовательскую систему:
Пропуск Wordpress хэшируется с помощью phpass.
Entity \ WpUsers(генерируется доктриной):
/**
* WpUsers
*
* @ORM\Table(name="wp_users", indexes={@ORM\Index(name="user_nicename", columns={"user_nicename"}), @ORM\Index(name="user_login_key", columns={"user_login"}), @ORM\Index(name="user_email", columns={"user_email"})})
* @ORM\Entity(repositoryClass="App\Repository\WpUsersRepository")
*/
class WpUsers
{
/**
* @var int
*
* @ORM\Column(name="ID", type="bigint", nullable=false, options={"unsigned"=true})
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="user_login", type="string", length=60, nullable=false)
*/
private $userLogin = '';
/**
* @var string
*
* @ORM\Column(name="user_pass", type="string", length=255, nullable=false)
*/
private $userPass = '';
/**
* @var string
*
* @ORM\Column(name="user_nicename", type="string", length=50, nullable=false)
*/
private $userNicename = '';
/**
* @var string
*
* @ORM\Column(name="user_email", type="string", length=100, nullable=false)
*/
private $userEmail = '';
/**
* @var string
*
* @ORM\Column(name="user_url", type="string", length=100, nullable=false)
*/
private $userUrl = '';
/**
* @var \DateTime
*
* @ORM\Column(name="user_registered", type="datetime", nullable=false, options={"default"="0000-00-00 00:00:00"})
*/
private $userRegistered = '0000-00-00 00:00:00';
/**
* @var string
*
* @ORM\Column(name="user_activation_key", type="string", length=255, nullable=false)
*/
private $userActivationKey = '';
/**
* @var int
*
* @ORM\Column(name="user_status", type="integer", nullable=false)
*/
private $userStatus = '0';
/**
* @var string
*
* @ORM\Column(name="display_name", type="string", length=250, nullable=false)
*/
private $displayName = '';
Entity \ User.php:
<?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="json_array")
*/
private $roles = [];
/**
* @ORM\OneToOne(targetEntity="App\Entity\WpUsers", cascade={"persist", "remove"})
* @ORM\JoinColumn(name="wp_user_id", referencedColumnName="ID",nullable=false)
*/
private $wpUser;
public function getId(): ?int
{
return $this->id;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUsername(): string
{
return $this->getWpUser()->getUserLogin();
}
/**
* @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()
{
return $this->getWpUser()->getUserPass();
}
/**
* @see UserInterface
*/
public function getSalt()
{
// not needed for apps that do not check user passwords
}
/**
* @see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getWpUser(): ?WpUsers
{
return $this->wpUser;
}
public function setWpUser(WpUsers $wpUser): self
{
$this->wpUser = $wpUser;
return $this;
}
}
security.yaml:
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
# encoders:
# App\Entity\WpUsers:
# algorithm: bcrypt
providers:
# in_memory: { memory: ~ }
app_user_provider:
entity:
class: App\Entity\User
property: wpUser.userLogin
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
guard:
authenticators:
- App\Security\LoginFormAuthenticator
remember_me:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
Безопасность \ LoginFormAuthenticator:
namespace App\Security;
// use ...
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
use TargetPathTrait;
private $entityManager;
private $urlGenerator;
private $csrfTokenManager;
// private $passwordEncorder;
private $router;
public function __construct(
EntityManagerInterface $entityManager,
UrlGeneratorInterface $urlGenerator,
CsrfTokenManagerInterface $csrfTokenManager,
// UserPasswordEncoderInterface $passwordEncorder,
// PasswordHash $passwordHash
RouterInterface $router
)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
// $this->passwordEncorder = $passwordEncorder;
$this->router = $router;
$this->passwordHash = new PasswordHash(8,false);
}
public function supports(Request $request)
{
return 'app_login' === $request->attributes->get('_route')
&& $request->isMethod('POST');
}
public function getCredentials(Request $request)
{
$credentials = [
'userLogin' => $request->request->get('userLogin'),
'password' => $request->request->get('password'),
'csrf_token' => $request->request->get('_csrf_token'),
];
$request->getSession()->set(
Security::LAST_USERNAME,
$credentials['userLogin']
);
return $credentials;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token)) {
throw new InvalidCsrfTokenException();
}
$wpUser = $this->entityManager->getRepository(WpUsers::class)->findOneBy(['userLogin' => $credentials['userLogin']]);
if (!$wpUser) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('User Login could not be found.');
}
$user = $this->entityManager->getRepository(User::class)->findOneBy(['wpUser' => $wpUser ]);
if(!$user){
$user = new USER();
$user->setWpUser($wpUser);
$this->entityManager->persist($user);
$this->entityManager->flush();
}
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token)) {
throw new InvalidCsrfTokenException();
}
// return $this->passwordEncorder->isPasswordValid($user, $credentials['password']);
return $this->passwordHash->CheckPassword($credentials['password'],$user->getPassword());
// Check the user's password or other credentials and return true or false
// If there are no credentials to check, you can just return true
throw new \Exception('TODO: check the credentials inside '.__FILE__);
}
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'));
// throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
return new RedirectResponse($this->router->generate('commandes'));
}
protected function getLoginUrl()
{
return $this->urlGenerator->generate('app_login');
}
}
login.twig.html:
{% extends 'myBase.html.twig' %}
{% block title %}Log in!{% endblock %}
{% block body %}
<form method="post">
{% if error %}
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<label for="inputUserLogin" class="sr-only">User Login</label>
<input type="text" value="{{ last_username }}" name="userLogin" id="inputUserLogin" class="form-control" placeholder="User Login" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required>
<input type="hidden" name="_csrf_token"
value="{{ csrf_token('authenticate') }}"
>
<!-- Uncomment this section and add a remember_me option below your firewall to activate remember me functionality.
See https://symfony.com/doc/current/security/remember_me.html -->
<div class="checkbox mb-3">
<label>
<input type="checkbox" name="_remember_me"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary" type="submit">
Sign in
</button>
</form>
{% endblock %}