Quantcast
Channel: Active questions tagged symfony4 - Stack Overflow
Viewing all articles
Browse latest Browse all 3927

Add remember me to Symfony 4.2 Security with custom User Entity

$
0
0

I'm working with Symfony 4.2,

I'm working with Security Component and I'm trying to add remember me.

At first Remember Me worked for me, but when my User Entity Became Customized, the remember me doesn't work anymore,

#My Custom User:I'm connected to a wordpress DB that I can't do any change on it ( I must Read Only ),And I need to add some field to the User, So I have to create a new table User OneToOne with WpUsers (wordpress Users),

So, I use doctrine to create entity from the existing DB, I didn't touch to those entities, I just create my User Entity just to add roles field to the User System:

Wordpress pass is hashed with phpass.

#Entity\WpUsers (generated by doctrine):

/** * 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:

<?phpnamespace 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

Security\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 %}

Viewing all articles
Browse latest Browse all 3927

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>