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

5

我想创建一个服务提供者,以便使用FOSUserBundle通过电子邮件而不是用户名进行登录。

首先,我按照此处的文档(点击跳转)在我的security.yml文件中编写了以下内容:

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

根据FOS文档,我按照这些步骤逐一操作。但在MyUserManager.php中,我按照这里的另一个问题写了以下代码:here
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 %}

“只允许用户用电子邮件字段登录而不是用户名,这是一个好的方式吗?”

2
是的,你可以这样使用。我正在这样工作,一切都很好。 - Mert Öksüz
@MertÖKSÜZ 谢谢您的回复,如果它很好,我希望它能帮助其他Symfony爱好者! - french_dev
我也希望如此 :) 谢谢。 - Mert Öksüz
这也是一个相关的文章:https://dev59.com/V2oy5IYBdhLWcg3wA5aC#21064627 - Anil
1个回答

4

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

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

由于用户名始终使用电子邮件字段值进行设置,创建CustomUserManager是否有用? 如果用户名始终等于电子邮件,那么loadByUsername将起作用,就像您在setEmailsetEmailCanonical中的实体中所做的那样。

这只是额外的安全措施吗?

编辑

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

也许您需要查看此答案:https://dev59.com/V2oy5IYBdhLWcg3wA5aC#21064627


1
据我在 Symfony 文档中阅读到的内容,身份验证过程取决于“用户提供者”。当用户提交电子邮件和密码时,身份验证层会要求配置的用户提供程序返回给定参数(此处为电子邮件)的用户对象。因此,我重写了 UserManger 来保持符合文档。我只是按照文档的指导来确保这是最佳实践。希望您能理解我想做什么,并且如果需要的话,它可以帮助到您。 - french_dev
1
好的,现在对我来说很清楚了。我有很多需要学习和阅读关于Symfony中如何处理安全性的文档资料。 我会去搜索相关内容,并且肯定会应用你的逻辑来确保最大程度的使用案例。谢谢你的回复。 - chalasr
不用谢。我在这里发布这个问题是为了确保我已经创建了正确的实践/方法,并且如果有其他开发人员的建议,那就更好了。如果这能帮到你,我很高兴。 - french_dev
1
请查看我回答中的编辑,我添加了一个关于表单构建/验证的链接,这对您的注册/登录表单可能有帮助。 - chalasr
谢谢,我现在只是试着跟着这个步骤走。 - french_dev

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