Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Symfony 3,填充令牌并刷新用户_Php_Symfony_Hwioauthbundle_Symfony 3.3 - Fatal编程技术网

Php Symfony 3,填充令牌并刷新用户

Php Symfony 3,填充令牌并刷新用户,php,symfony,hwioauthbundle,symfony-3.3,Php,Symfony,Hwioauthbundle,Symfony 3.3,我有一个带有电子邮件字段的实体用户表单: ->add('email', EmailType::class, [ 'constraints' => [ new NotBlank(), new Email([ 'checkMX' => true, ])

我有一个带有电子邮件字段的实体用户表单:

->add('email', EmailType::class, [
                'constraints' => [
                    new NotBlank(),
                    new Email([
                        'checkMX' => true,
                    ])
                ],
                'required' => true
            ])
当我编辑电子邮件时,比如
test@gmail.com1
和提交表单它向我显示错误“此值不是有效的电子邮件地址”。这没关系,但在symfony将错误的电子邮件填充到令牌中之后,当我转到任何其他页面或只是重新加载页面时,我得到以下信息:

警告:在所选用户中找不到安全用户名 提供者

我想问题是:为什么symfony将错误的验证失败的电子邮件填充到令牌中,以及我如何防止它

控制器:

public function meSettingsAction(Request $request)
    {

        $user = $this->getUser();
        $userUnSubscribed = $this->getDoctrine()->getRepository('AppBundle:UserUnsubs')->findOneBy(
            [
                'email' => $user->getEmail(),
            ]
        );

        $form = $this->createForm(UserSettingsType::class, $user);
        $form->get('subscribed')->setData(!(bool)$userUnSubscribed);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            /**
             * @var $user User
             */
            $user = $form->getData();

            /** @var UploadedFile $avatar */
            $avatar = $request->files->get('user_settings')['photo'];

            $em = $this->getDoctrine()->getManager();

            if ($avatar) {
                $avatar_content = file_get_contents($avatar->getRealPath());
                $avatarName = uniqid().'.jpg';
                $oldAvatar = $user->getPhoto();
                $user
                    ->setState(User::PHOTO_STATE_UNCHECKED)
                    ->setPhoto($avatarName);
                $gearmanClient = $this->get('gearman.client');
                $gearmanClient->doBackgroundDependsOnEnv(
                    'avatar_content_upload',
                    serialize(['content' => $avatar_content, 'avatarName' => $avatarName, 'oldAvatar' => $oldAvatar])
                );
            }

            $subscribed = $form->get('subscribed')->getData();
            if ((bool)$userUnSubscribed && $subscribed) {
                $em->remove($userUnSubscribed);
            } elseif (!(bool)$userUnSubscribed && !$subscribed) {
                $userUnSubscribed = new UserUnsubs();
                $userUnSubscribed->setEmail($form->get('email')->getData())->setTs(time());
                $em->persist($userUnSubscribed);
            }
            $user->setLastTs(time());
            $em = $this->getDoctrine()->getManager();
            $em->persist($user);
            $em->flush();

            $this->get('user.manager')->refresh($user);

            return $this->redirectToRoute('me');
        }

        return $this->render(
            ':user:settings.html.twig',
            [
                'form' => $form->createView(),
            ]
        );
    }
UPD: 如果我在OAuthProvider中更改,它可以正常工作:

/**
 * @param \Symfony\Component\Security\Core\User\UserInterface $user
 *
 * @return \Symfony\Component\Security\Core\User\UserInterface
 */
public function refreshUser(UserInterface $user)
{
    return $this->loadUserByUsername($user->getName());
}
致:

但它似乎是肮脏的黑客


谢谢。

您的用户令牌似乎已通过表单更新,即使电子邮件约束停止刷新

你能检查一下你的表单是否通过了isValid函数吗? 您可以尝试使用事件侦听器或验证器来避免它


通过事件提交,您应该能够检查电子邮件的完整性,然后添加FormError以避免刷新用户。

这是一个棘手的问题,多亏了存储库,更容易隔离问题。您正在将用户对象从身份验证令牌绑定到
createForm()
方法。之后

$form->handleRequest($request)
在令牌用户对象更新时取消电子邮件

我首先想通过在
用户
实体中实现来解决这个问题,但这不起作用,因为比较对象已经设置了错误的电子邮件地址

实现EqualTableInterface接口也可能很有用,该接口定义了一个方法来检查用户是否等于当前用户。此接口需要一个isEqualTo()方法。)

然后,我考虑强制从db重新加载用户并重置安全令牌,但最后我想到,如果表单失败,只从数据库刷新当前用户对象就足够了:

$this->get('doctrine')->getManager()->refresh($this->getUser());`
在控制器中,这将解决您的问题

/**
 * @Route("/edit_me", name="edit")
 * @Security("has_role('ROLE_USER')")
 */
public function editMyselfAction(Request $request) {
    $form = $this->createForm(User::class, $this->getUser());

    if ($request->isMethod(Request::METHOD_POST)) {
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $user = $form->getData();
            $em = $this->getDoctrine()->getManager();
            $em->persist($user);
            $em->flush();
        } else {
            $this->get('doctrine')->getManager()->refresh($this->getUser());
        }
    }

    return $this->render(':security:edit.html.twig',['form' => $form->createView()]);
}
替代解决方案


结果产生了一些关于和的有价值的输入,为解决问题提供了更复杂的方法

你能展示你的控制器吗?@AlessandroMinoccheri我已经在问题中添加了控制器代码。为什么
refreshUser()
即使电子邮件错误也会被调用?请添加有关serurity.yml配置的更多信息。@lordrodos我不知道它为什么调用。问题在于另一件事,重读问题。您的
UserSettingsType
链接到哪个实体?你的用户是什么?
UserInterface
的简单实现,或者类似于
FOSUserBundle
这样的外部捆绑包的东西?如前所述,我们能否获得您的
security.yml
?我们真的需要更多的信息来重现这个问题。你是认真的吗?我理解你为什么仍然坚持下去,我们是来免费帮助你的,请礼貌一点。我已经提到了在提交表格后正在更新,如果表格无效的话。正如您在代码中看到的:`if($form->isSubmitted()&&&$form->isValid()){`存在检查验证器,如果表单无效,for将不会在实体中填充数据。谢谢您的注意,但这是一个肮脏的黑客行为:D我已经在github上的symfony/symfony存储库中发布了一个问题,并将其提供给了我的存储库。这不是填充令牌的正常行为。我已经有另一个肮脏的黑客行为,即b嗯,老实说,我不认为这是一个肮脏的黑客,但这是一个必要的解决方案,因为你如何将$用户从令牌对象绑定到表单。这是预期的行为。如果你想避免它,你应该创建一个新的空用户对象,用当前登录的用户需要的数据初始化它,并绑定它。o表单。如果表单有效,您可以手动将提交的用户对象映射到令牌中的用户对象。只是为了完整性。该表单被视为SRP而不是bug。因此,这是对您问题的有效回答。您说服了我)我已更新了答案,如果您想扩展创建数据传输的方法,请告诉我对象或分离安全用户主题。
/**
 * @Route("/edit_me", name="edit")
 * @Security("has_role('ROLE_USER')")
 */
public function editMyselfAction(Request $request) {
    $form = $this->createForm(User::class, $this->getUser());

    if ($request->isMethod(Request::METHOD_POST)) {
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $user = $form->getData();
            $em = $this->getDoctrine()->getManager();
            $em->persist($user);
            $em->flush();
        } else {
            $this->get('doctrine')->getManager()->refresh($this->getUser());
        }
    }

    return $this->render(':security:edit.html.twig',['form' => $form->createView()]);
}