电子邮件验证错误Symfony 4后会话死亡

时间:2019-01-05 10:56:45

标签: symfony symfony-forms symfony4

我有一个表格,用户可以更改为自己的电子邮件。但是,当发生验证错误或某些因约束失败的会话死亡时,用户将被重定向到登录页面。重要的是要注意,用户是通过数据库中的用户和密码进行身份验证的。感谢您的帮助

更新

我刚刚添加了User.php文件以获取更多详细信息。

namespace App\Form;

class ChangeEmailType extends AbstractType
{
    private $translator;
    private $transformer;

    public function __construct(TranslatorInterface $translator, DateTimeToStringTransformer $transformer)
    {
        $this->transformer = $transformer;
        $this->translator = $translator;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('email', EmailType::class, array(
            'required' => true,
            'label' => $this->translator->trans('email'),
            'attr' => array('class' => 'form-control')
        ))
        ->add('updationDate', HiddenType::class, array(
            'required' => true,
            'label' => false,
        ));

        $builder->get('updationDate')->addModelTransformer($this>transformer);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'App\Entity\User',
            'attr' => array('class' => 'change-email-form')
        ));
    }
}

UserController.php

/**
 * @Security("has_role('ROLE_USER')")
 * @Route("/profile/change-email", name="change email")
 */
public function changeEmail(Request $request)
{
    $user = $this->getUser();
    $form = $this->createForm(ChangeEmailType::class, $user);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid())
    {
        try
        {
            $this->entityManager->lock($this->getUser(), LockMode::OPTIMISTIC, $user->getUpdationDate());
            $this->entityManager->flush();
            $this->addFlash('success', $this->translator->trans('email_is_successfully_changed'));
            return $this->redirectToRoute('dashboard');
        }
        catch (OptimisticLockException $exception)
        {
            $this->addFlash('success', $this->translator->trans('data_is_outdated_try_again'));
            return $this->redirectToRoute('change email');
        }
    }

    return $this->render('app/pages/profile/change-email.html.twig', array(
        'form' => $form->createView()
    ));
}

User.php

namespace App\Entity;

use DateTime;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @ORM\HasLifecycleCallbacks()
 * @ORM\Table(name="users")
 * @UniqueEntity(fields={"email"})
 */
class User implements UserInterface
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @Assert\Length(
     *     min = 6,
     *     minMessage = "Password should by at least 6 characters long",
     *     groups={"registration"}
     * )
     * @Assert\Type(
     *     type="alnum",
     *     message="Password should contains only numbers and letters",
     *     groups={"registration"}
     * )
     * @Assert\NotBlank()
     * @ORM\Column(type="text", nullable=true)
     */
    private $password;

    /**
     * @Assert\NotBlank(message="field_is_required")
     * @Assert\Email(message="email_is_invalid")
     * @ORM\Column(type="string", length=255, unique=true)
     */
    private $email;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $theme;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $facebookId;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $linkedinId;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $passwordRecoveryHash;

    /**
     * @ORM\Column(type="integer")
     */
    private $status;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $emailConfirmationHash;

    /**
     * @ORM\Column(type="datetime")
     * @ORM\Version
     */
    private $updationDate;

    /**
     * @ORM\Column(type="datetime")
     */
    private $creationDate;

    /**
     * @ORM\PrePersist()
     */
    public function prePersist(): void
    {
        $this->creationDate = new DateTime();
        $this->theme = 'light';
        $this->status = 0;
    }

    public function getRoles()
    {
        return ['ROLE_USER'];
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function getSalt()
    {
        return 'salt';
    }

    public function getUsername()
    {
        return $this->email;
    }

    public function eraseCredentials()
    {
         // TODO: Implement eraseCredentials() method.
    }

    public function getId()
    {
        return $this->id;
    }

    public function setId($id): void
    {
        $this->id = $id;
    }

    public function setPassword($password): void
    {
        $this->password = $password;
    }

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email): void
    {
        $this->email = $email;
    }

    public function getUpdationDate()
    {
        return $this->updationDate;
    }

    public function setUpdationDate($updationDate): void
    {
        $this->updationDate = $updationDate;
    }

    public function getCreationDate()
    {
        return $this->creationDate;
    }

    public function setCreationDate($creationDate): void
    {
        $this->creationDate = $creationDate;
    }

    public function getTheme()
    {
        return $this->theme;
    }

    public function setTheme($theme): void
    {
        $this->theme = $theme;
    }

    public function getPasswordRecoveryHash()
    {
        return $this->passwordRecoveryHash;
    }

    public function setPasswordRecoveryHash($passwordRecoveryHash): void
    {
        $this->passwordRecoveryHash = $passwordRecoveryHash;
    }

    public function getFacebookId()
    {
        return $this->facebookId;
    }

    public function setFacebookId($facebookId): void
    {
        $this->facebookId = $facebookId;
    }

    public function getLinkedinId()
    {
        return $this->linkedinId;
    }

    public function setLinkedinId($linkedinId): void
    {
        $this->linkedinId = $linkedinId;
    }

    public function getEmailConfirmationHash()
    {
        return $this->emailConfirmationHash;
    }

    public function setEmailConfirmationHash($emailConfirmationHash): void
    {
        $this->emailConfirmationHash = $emailConfirmationHash;
    }

    public function getStatus()
    {
        return $this->status;
    }

    public function setStatus($status): void
    {
        $this->status = $status;
    }
}

1 个答案:

答案 0 :(得分:0)

所以我遇到了同样的问题,但是我通过不将对象User传递给formType来解决了它。 这是我的代码

    $user = $this->getUser();

    // don't pass pass $user as parameter
    $form = $this->createForm(ChangeEmailType::class);
    $form->handleRequest($request);

    if ($form->isSubmitted()) {
        $em = $this->getDoctrine()->getManager();
        $currentEmail = $user->getEmail();
        $newEmail = $form->get('email')->getData();
        $currentPassword = $form->get('currentPassword')->getData();

        // verify if the tow emails are different
        if ($currentEmail === $newEmail) {
            $form->get('email')->addError(new FormError('You must choose a different email.'));
        }

        // verify if the email is used by another user
        $userHasAlreadyThisEmail = $em->getRepository('App:User')->findOneBy(array('email' => $newEmail));
        if ($userHasAlreadyThisEmail && $userHasAlreadyThisEmail !== $user) {
            $form->get('email')->addError(new FormError('This email is already used.'));
        }

        // verify if the password is correct
        $verify = $this->verify($currentPassword, $user->getPassword());
        if ($verify === false) {
            $form->get('currentPassword')->addError(new FormError('Incorrect password.'));
        }
        if ($form->isValid()) {
            $this->addFlash('success', 'The email has been successfully modified.');
            $user->setEmail($newEmail);
            $em->flush();
            return $this->redirectToRoute('profile_change_email');
        }
    }


    public function verify($input, $existingHash)
    {
        $hash = password_verify($input, $existingHash);

        return $hash === true;
     }