简体   繁体   English

通过Symfony 2中的其他字段对用户进行身份验证和注册

[英]Authenticate and register a user by additional fields in Symfony 2

I have Symfony 2.3 project. 我有Symfony 2.3项目。 FOS User Bundle and Sonata User Bundle installed. 已安装FOS用户捆绑包和Sonata用户捆绑包。 Now I need to login a user not only by user name and password but by a card number and PIN code. 现在,我不仅需要通过用户名和密码登录用户,还需要通过卡号和PIN码登录。 A user can have only one card but the card could be connected with several users. 一个用户只能拥有一张卡,但是该卡可以与多个用户连接。 And the algorithm is when a user has entered his user name, password, card number and PIN I should check all the data and if there are the user with the card in the DB he is logging in. But if there card info is valid but the entered user data is invalid I should register the new user with the user name and password in the DB and log in him right away. 算法是当用户输入用户名,密码,卡号和PIN码时,我应该检查所有数据,以及是否有该用户登录到他正在登录的数据库中。但是,如果有卡信息有效,但输入的用户数据无效,我应该在数据库中用用户名和密码注册新用户并立即登录。

I've created the Card Entity with the two fields and relation with User entity. 我创建了具有两个字段以及与用户实体的关系的卡实体。 The User entity was extended from Sonata User Bundle. User实体是从Sonata User Bundle扩展的。 This is the Card entity code: 这是卡实体代码:

namespace Acme\BoardBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use Acme\UserBundle\Entity\User as User;

/**
 * @ORM\Entity
 * @ORM\Table(name="yam_card")
 */
class Card
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank()
     * @Assert\Length(min = "6")
     * @Assert\Length(max = "6")
     */
    protected $number;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank()
     * @Assert\Length(min = "4")
     * @Assert\Length(max = "4")
     */
    protected $pin;

    /**
     * @ORM\OneToMany(targetEntity="Acme\UserBundle\Entity\User", mappedBy="card", cascade={"remove"})
     */
    protected $users;


    public function __toString()
    {
      return (string)$this->number;
    }

    public function __construct()
    {
        $this->users = new ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set number
     *
     * @param string $number
     */
    public function setNumber($number)
    {
        $this->number = $number;
    }

    /**
     * Get number
     *
     * @return string 
     */
    public function getNumber()
    {
        return $this->number;
    }

    /**
     * Set pin
     *
     * @param string $pin
     */
    public function setPin($pin)
    {
        $this->pin = $pin;
    }

    /**
     * Get pin
     *
     * @return string 
     */
    public function getPin()
    {
        return $this->pin;
    }

    /**
     * Add users
     *
     * @param \Acme\UserBundle\Entity\User $users
     * @return Card
     */
    public function addUser(\Acme\UserBundle\Entity\User $users)
    {
        $this->users[] = $users;

        return $this;
    }

    /**
     * Remove users
     *
     * @param \Acme\UserBundle\Entity\User $users
     */
    public function removeUser(\Acme\UserBundle\Entity\User $users)
    {
        $this->users->removeElement($users);
    }

    /**
     * Get users
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getUsers()
    {
        return $this->users;
    }
}

And a peace of code of the User entity with the relation: 与用户实体的代码之间的和平关系:

namespace Acme\UserBundle\Entity;

use Sonata\UserBundle\Entity\BaseUser as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use \Acme\BoardBundle\Entity\Card;

/**
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 * @ORM\Table(name="fos_user")
 */
class User extends BaseUser
{
    ...

    protected $card;

    /**
     * Set card
     *
     * @param \Acme\BoardBundle\Entity\Card $card
     * @return Card
     */
    public function setCard(\Acme\BoardBundle\Entity\Card $card)
    {
        $this->card = $card;

        return $this;
    }

    /**
     * Get card
     *
     * @return \Acme\BoardBundle\Entity\Card
     */
    public function getCard()
    {
        return $this->card;
    }
}

User.orm.xml: User.orm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                  http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

    <entity name="Acme\UserBundle\Entity\User" table="fos_user">

        ...

        <many-to-one field="card" target-entity="Acme\BoardBundle\Entity\Card" inversed-by="users">
            <join-column name="card" referenced-column-name="id" />
        </many-to-one>
    </entity>
</doctrine-mapping>

The question is what class (or interface) should I redefine to add the check for the two additional parameters (card number and PIN) and how can I make it? 问题是我应该重新定义哪个类(或接口)以添加对两个附加参数(卡号和PIN)的检查,我该如何做?

I've found the UserProvider class which implements UserProviderInterface. 我找到了实现UserProviderInterface的UserProvider类。 But the class has loadUserByUsername() method which loads user by user name and works with the user object already. 但是该类具有loadUserByUsername()方法,该方法按用户名加载用户并已与该用户对象一起使用。 The class doesn't receive a responce object from where I can get the card number and PIN code from the login form. 该类没有收到响应对象,我可以从登录表单中获取卡号和PIN码。 Also I've found a solution for checking additional user status parameter by extending UserChecker class from Symfony Security Core. 另外,我还找到了一种通过扩展Symfony Security Core中的UserChecker类来检查其他用户状态参数的解决方案。 There checkPreAuth and checkPostAuth methods was used but there I can also work with the User object only. 那里使用了checkPreAuth和checkPostAuth方法,但在那里我也只能使用User对象。 So I guess that I should use some listener or something like that to check the receiving user name, password, card number and PIN code from the request on equality with the users which was registered in my DB. 因此,我想我应该使用某种侦听器或类似的方法来检查与数据库中注册的用户是否相等的请求中的接收用户名,密码,卡号和PIN码。 But I can't find the entering point. 但是我找不到切入点。

You can manually login a use once you are sure the passed Card is valid and belongs to that User . 一旦确定所传递的Card有效并且属于该User就可以手动登录使用。 Make sure you trigger an InteractiveLoginEvent to let all listeners know the login happened: 确保触发InteractiveLoginEvent以使所有侦听器都知道登录已发生:

    // 'main' is the name of the firewall to login to
    $token = new UsernamePasswordToken($validatedCard->getUser(), null, 'main', $validatedCard->getUser()->getRoles());
    $this->get('security.token_storage')->setToken($token);

    // Notify the dispatcher, so LoginListener is triggered
    $loginEvent = new InteractiveLoginEvent($request, $token);
    $this->get('event_dispatcher')->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM