FOSUserBundle 使用服务提供商的电子邮件登录,最佳实践


FOSUserBundle login with email with service Provider, best practice

我正在寻找一个服务提供商,以便使用电子邮件登录,而不是使用FOSUserBundle的用户名登录。

首先,我根据这里的文档在我的security.yml文件中写了这个:

security:
    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email

根据FOS文档,我一一遵循这些步骤。

除了在MyUserManager中.php我写了这个(根据这里堆栈的另一个问题):

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;
    }
}

当然,我更改了 User 类以实现特定的 getter 和 setter,如下所示:

namespace Acme'UserBundle'Entity;
use FOS'UserBundle'Entity'User as BaseUser;
use Doctrine'ORM'Mapping as ORM;
/**
 * @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);
    }
    // ...
}

但是我欠 FOSUser 模板表单app'Resources'FOSUserBundle'views'Security'login.html.twig像这样:

{% block fos_user_content %}
  <form action="{{ path("fos_user_security_check") }}" method="post">
    <input type="hidden" name="_csrf_token" value="{{ csrf_token }}"/>
    <label class="" for="username">E-mail</label>
    <input type="email" class="" id="username" name="_username" required="required"/>
    <label class="" for="password">{{ 'security.login.password'|trans }}</label>
    <input class="" type="password" id="password" name="_password" required="required"/>
    <label class="" for="remember_me">
      <input type="checkbox" id="remember_me" name="_remember_me" class="">
      <span class="">{{ 'security.login.remember_me'|trans }}</span>
    </label>
    <button class="" type="submit" id="_submit" name="_submit" value="{{ 'security.login.submit'|trans }}">
      LogIn
    </button>
  </form>
{% endblock fos_user_content %}

这是仅允许用户使用电子邮件字段登录的好方法,并且 不是用户名?

您的方法完美地恢复了在 FOSUserBundle 上设置电子邮件密码身份验证的所有强制性更改。

目前,我在实体和安全配置中仅使用相同的配置(不需要模板,因为我的登录是在 AJAX 中完成的)。我唯一的疑问是以下几点:

由于username始终使用 email 字段值进行设置,因此创建自定义用户管理器是否有用?
如果用户名始终等于电子邮件,则 loadByUsername 将起作用,就像您的实体在 setEmailsetEmailCanonical 中所做的那样。

它只是一种额外的安全性吗?

编辑

从用户名更改为电子邮件可能涉及更改表单构建/验证中的一些行为。

也许你必须看看这个答案:https://stackoverflow.com/a/21064627/4363634