FOSUserBundle使用电子邮件登录(Symfony2)

15

我对Symfony 2.0.x中的FOSUserBundle有一个问题。 在文档中,您可以找到一种方法来更改登录以使用用户名和电子邮件。这很好用!但我想要只使用电子邮件登录。因此,我在我的CustomUserManager(扩展自原始版本)中添加了一个函数,以确保您只能使用电子邮件进行登录。

namespace Frontend\UserBundle\Model;

use FOS\UserBundle\Entity\UserManager;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;

class CustomUserManager extends UserManager
{
    public function loadUserByUsername($email)
    {
        /*$user = $this->findUserByUsernameOrEmail($username);

        if (!$user) {
            throw new UsernameNotFoundException(sprintf('No user with name "%s" was found.', $username));
        }

        return $user;*/

        //Change it to only email (Default calls loadUserByUsername -> we send it to our own loadUserByEmail)
        return $this->loadUserByEmail($email);
    }

    public function loadUserByEmail($email)
    {
        $user = $this->findUserByEmail($email);

        if (!$user) {
            throw new UsernameNotFoundException(sprintf('No user with email "%s" was found.', $email));
        }

        return $user;

    }
}

但是现在我有一个问题,我需要控制保存在会话中的值。他将我的用户名保存在会话中,当系统检查时,将不会有可用的电子邮件(因为他只检查电子邮件)。

所以我的问题是如何/在哪里可以更改存储在用户名变量中的值。

谢谢!

2个回答

27

可以通过在User实体中覆盖setter来实现:

<?php

namespace Acme\UserBundle\Entity;

use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * @ORM\Entity(repositoryClass="Acme\UserBundle\Entity\UserRepository")
 * @ORM\Table(name="users")
 */
class User extends BaseUser
{

    // ...

    // override methods for username and tie them with email field

    /**
     * Sets the email.
     *
     * @param string $email
     * @return User
     */
    public function setEmail($email)
    {
        $this->setUsername($email);

        return parent::setEmail($email);
    }

    /**
     * Set the canonical email.
     *
     * @param string $emailCanonical
     * @return User
     */
    public function setEmailCanonical($emailCanonical)
    {
        $this->setUsernameCanonical($emailCanonical);

        return parent::setEmailCanonical($emailCanonical);
    }

    // ...

}

从您的问题中并不清楚,但根据您的命名空间,我假设您有自己的子捆绑包,将FOSUserBundle用作其父捆绑包(如FOSUserBundle文档,示例“b”)。

如果是这样,您可以轻松地覆盖表单和模板以从UI中删除任何username字段并将它们替换为email字段。由于您已经按照上述方式覆盖了电子邮件设置器,因此username属性将被正确填充。

尽管这种方法可行,但并不是很好的解决方案。缺点是您仍然会在数据库中拥有usernameusernameCanonical列。我们最初想要完全删除它们,但这将需要在FOSUserBundle中进行太多更改(用户名属性是由\FOS\UserBundle\Model\UserInterface所需的,并且捆绑包代码依赖于它)。


16

我找到了一个非常简单的解决方案,可能不是最好的,但简单就是力量!;)

我在这里写下来,以防对任何人有用。

我将用户名/电子邮件登录选项放在提供者中:

在app/conf/security.yml中:

providers:
    fos_userbundle:
        id: fos_user.user_provider.username_email

然后在您的登录表单视图中,我仅允许使用input type="email"进行登录:

<input type="email" class="form-control" id="username" placeholder="E-Mail" name="_username" required="required"/>

嘿,感谢这个 NoFlag - 这对我来说完美地解决了问题。我在配置参考中寻找它。但是,因为这实际上是在安全配置中,所以它不在 FOSUserBundle 配置参考 中。对于其他像我一样的人 - 你必须在 FOSUserBundle 的安全配置文档 中寻找它。 - jfgrissom
这是HTML5的输入类型,仅适用于最近的浏览器。 - khaled_webdev
1
虽然这样做是可行的,而且也有意义,但请记住,用户可以打开开发工具并将 type="email" 更改为 type="text",然后使用用户名登录。显然,这取决于您的情况,是否会造成问题。 - bassplayer7
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/logging_by_username_or_email.rst - Sithu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接