Symfony2:如果缺少某些字段,请在登录后让用户完成注册

ale*_*x88 8 oauth symfony symfony-2.1 hwioauthbundle

我正在使用HWIOAuthBundle让用户使用Oauth登录,我创建了一个自定义用户提供程序,以便在用户不存在的情况下创建用户:

public function loadUserByOAuthUserResponse(UserResponseInterface $response)
{
    $attr = $response->getResponse();
    switch($response->getResourceOwner()->getName()) {
        case 'google':
            if(!$user = $this->userRepository->findOneByGoogleId($attr['id'])) {
                if(($user = $this->userRepository->findOneByEmail($attr['email'])) && $attr['verified_email']) {
                    $user->setGoogleId($attr['id']);
                    if(!$user->getFirstname()) {
                        $user->setFirstname($attr['given_name']);
                    }
                    if(!$user->getLastname()) {
                        $user->setLastname($attr['family_name']);
                    }
                    $user->setGoogleName($attr['name']);
                }else{
                    $user = new User();
                    $user->setUsername($this->userRepository->createUsernameByEmail($attr['email']));
                    $user->setEmail($attr['email']);
                    $user->setFirstname($attr['given_name']);
                    $user->setLastname($attr['family_name']);
                    $user->setPassword('');
                    $user->setIsActive(true);
                    $user->setGoogleId($attr['id']);
                    $user->setGoogleName($attr['name']);
                    $user->addGroup($this->groupRepository->findOneByRole('ROLE_USER'));
                    $this->entityManager->persist($user);
                }
            }
            break;
        case 'facebook':
            if(!$user = $this->userRepository->findOneByFacebookId($attr['id'])) {
                if(($user = $this->userRepository->findOneByEmail($attr['email'])) && $attr['verified']) {
                    $user->setFacebookId($attr['id']);
                    if(!$user->getFirstname()) {
                        $user->setFirstname($attr['first_name']);
                    }
                    if(!$user->getLastname()) {
                        $user->setLastname($attr['last_name']);
                    }
                    $user->setFacebookUsername($attr['username']);
                }else{
                    $user = new User();
                    $user->setUsername($this->userRepository->createUsernameByEmail($attr['email']));
                    $user->setEmail($attr['email']);
                    $user->setFirstname($attr['first_name']);
                    $user->setLastname($attr['last_name']);
                    $user->setPassword('');
                    $user->setIsActive(true);
                    $user->setFacebookId($attr['id']);
                    $user->setFacebookUsername($attr['username']);
                    $user->addGroup($this->groupRepository->findOneByRole('ROLE_USER'));
                    $this->entityManager->persist($user);
                }
            }
            break;
    }

    $this->entityManager->flush();


    if (null === $user) {
        throw new AccountNotLinkedException(sprintf("User '%s' not found.", $attr['email']));
    }

    return $user;
}
Run Code Online (Sandbox Code Playgroud)

问题是twitter例如没有给出电子邮件,或者我想在创建新用户之前包含一些额外的字段.有没有办法在创建之前将用户重定向到"完整注册"表单?

我试图添加一个请求监听器,在每个请求上,如果用户被记录,检查电子邮件是否存在,如果不存在,则重定向到complete_registration页面,但如果用户转到,它也将重定向主页,注销或其他任何内容,我只想在他试图访问某些用户限制页面时重定向他.

或者更好的是,在他提供所有必需的信息之前不要创建它.

ale*_*x88 6

我自己找到了解决方案,我手动创建了一个新的异常:

<?php

namespace Acme\UserBundle\Exception;

use Symfony\Component\Security\Core\Exception\AuthenticationException;
use HWI\Bundle\OAuthBundle\Security\Core\Exception\OAuthAwareExceptionInterface;

/**
 * IncompleteUserException is thrown when the user isn't fully registered (e.g.: missing some informations).
 *
 * @author Alessandro Tagliapietra http://www.alexnetwork.it/
 */
class IncompleteUserException extends AuthenticationException implements OAuthAwareExceptionInterface
{
    private $user;
    private $accessToken;
    private $resourceOwnerName;

    /**
     * {@inheritdoc}
     */
    public function setAccessToken($accessToken)
    {
        $this->accessToken = $accessToken;
    }

    /**
     * {@inheritdoc}
     */
    public function getAccessToken()
    {
        return $this->accessToken;
    }

    /**
     * {@inheritdoc}
     */
    public function getResourceOwnerName()
    {
        return $this->resourceOwnerName;
    }

    /**
     * {@inheritdoc}
     */
    public function setResourceOwnerName($resourceOwnerName)
    {
        $this->resourceOwnerName = $resourceOwnerName;
    }

    public function setUser($user)
    {
        $this->user = $user;
    }

    public function getUser($user)
    {
        return $this->user;
    }

    public function serialize()
    {
        return serialize(array(
            $this->user,
            $this->accessToken,
            $this->resourceOwnerName,
            parent::serialize(),
        ));
    }

    public function unserialize($str)
    {
        list(
            $this->user,
            $this->accessToken,
            $this->resourceOwnerName,
            $parentData
        ) = unserialize($str);
        parent::unserialize($parentData);
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,在我检查用户是否存在或我创建新用户时,在自定义Oauth用户提供程序中,我检查是否缺少必需的字段:

if (!$user->getEmail()) {
    $e = new IncompleteUserException("Your account doesn't has a mail set");
    $e->setUser($user);
    throw $e;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,用户将被重定向到登录表单,在会话中具有该异常,因此在登录页面中我做:

if($error instanceof IncompleteUserException) {
    $session->set(SecurityContext::AUTHENTICATION_ERROR, $error);
    return $this->redirect($this->generateUrl('register_complete'));
}
Run Code Online (Sandbox Code Playgroud)

它将被重定向到异常中具有$ user的表单,因此它只能询问丢失的信息,然后登录用户.