[英]Authenticate and register a user by additional fields in Symfony 2
我有Symfony 2.3项目。 已安装FOS用户捆绑包和Sonata用户捆绑包。 现在,我不仅需要通过用户名和密码登录用户,还需要通过卡号和PIN码登录。 一个用户只能拥有一张卡,但是该卡可以与多个用户连接。 算法是当用户输入用户名,密码,卡号和PIN码时,我应该检查所有数据,以及是否有该用户登录到他正在登录的数据库中。但是,如果有卡信息有效,但输入的用户数据无效,我应该在数据库中用用户名和密码注册新用户并立即登录。
我创建了具有两个字段以及与用户实体的关系的卡实体。 User实体是从Sonata User Bundle扩展的。 这是卡实体代码:
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;
}
}
与用户实体的代码之间的和平关系:
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:
<?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>
问题是我应该重新定义哪个类(或接口)以添加对两个附加参数(卡号和PIN)的检查,我该如何做?
我找到了实现UserProviderInterface的UserProvider类。 但是该类具有loadUserByUsername()方法,该方法按用户名加载用户并已与该用户对象一起使用。 该类没有收到响应对象,我可以从登录表单中获取卡号和PIN码。 另外,我还找到了一种通过扩展Symfony Security Core中的UserChecker类来检查其他用户状态参数的解决方案。 那里使用了checkPreAuth和checkPostAuth方法,但在那里我也只能使用User对象。 因此,我想我应该使用某种侦听器或类似的方法来检查与数据库中注册的用户是否相等的请求中的接收用户名,密码,卡号和PIN码。 但是我找不到切入点。
一旦确定所传递的Card
有效并且属于该User
就可以手动登录使用。 确保触发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.