代码之家  ›  专栏  ›  技术社区  ›  user3440145

Symfony 5.3用户通过用户名或电子邮件登录

  •  0
  • user3440145  · 技术社区  · 4 年前

    我正在将Symfony 3项目移植到Symfony 5.3。 我必须去掉fosuserbundle,但需要让现有用户能够通过用户名或电子邮件登录。用户必须能够选择输入用户名/密码还是电子邮件/密码。 我创建了一个用户类和登录表单,如基本教程中所述

    https://symfony.com/doc/current/security.html#a-create-your-user-class

    https://symfony.com/doc/current/security/form_login_setup.html

    我在userclass中添加了一个username属性(尽管maker bundle自动生成了“getUsername”-ggetter的弃用提示:“自Symfony 5.3以来,请改用getUserIdentifier”),并将用户数据从旧数据库迁移到新数据库。 登录现在可以很好地使用存储在数据库中的凭据,但只能通过电子邮件而不是用户名登录。

    让自动生成的登录表单/身份验证提供程序也能使用username,我缺少什么?

    0 回复  |  直到 4 年前
        1
  •  1
  •   Darko    4 年前

    您需要修改从Symfony文档中引用的代码,使其符合您的需求。事实上,它只允许通过电子邮件登录,但您需要额外添加用户名的可能性。

    首先修改登录表单以允许使用用户名。因此,在教程的示例中,我们需要将类型和名称更改为以下内容:

    <label for="inputEmailOrUsername">Email or Username</label>
    <input type="text" value="{{ last_username }}" name="email_or_username" id="inputEmailOrUsername" class="form-control" required autofocus>
    

    下一个是LoginFormAuthenticator(或它为您调用的任何东西)。修改 authenticate 方法来适应登录表单中的更改

    public function getCredentials(Request $request)
    {
        $credentials = [
            'email_or_username' => $request->request->get('email_or_username'),
            'password' => $request->request->get('password'),
            'csrf_token' => $request->request->get('_csrf_token'),
        ];
        
        ...
    }
    

    并修改 getUser 方法来查找电子邮件或用户名:

    public function getUser($credentials, UserProviderInterface $userProvider): ?User
    {
        ...
    
        $user = $this->entityManager->getRepository(User::class)->findByEmailOrUsername($credentials['email_or_username']);
    
        // ...
    }
    

    正如你所看到的,我已经更换了 findOneBy 使用不存在的方法调用存储库 findByEmailOrUsername 。继续在UserRepository类中创建此方法,使其类似于以下内容:

    public function findByEmailOrUsername(string $emailOrUsername)
    {
        return $this->createQueryBuilder('u')
            ->where('u.email = :emailOrUsername')
            ->orWhere('u.username = :emailOrUsername')
            ->setParameter('emailOrUsername', $emailOrUsername)
            ->getQuery()
            ->getOneOrNullResult();
    }
    

    这应该是代码的通用工作原型,以便使用用户名或电子邮件地址登录。请自行验证登录表单输入字段。


    更新 - 以适应最新的Symfony5 Authenticator更改 :

    供参考: Using the new Authenticator-based security

    而不是使用 getCredentials getUser 方法(它们已不存在),您应该使用 证明…是真实的 方法,通过将UserLoader作为第二个参数提供给UserBadge类来满足您的需求。

    public function authenticate(Request $request): PassportInterface
    {
        $emailOrUsername = $request->request->get('email_or_username');
        // ... get the rest of the parameters from the input bag
    
        // ... validate no parameter is empty
    
        return new Passport(
            new UserBadge($emailOrUsername, function ($userIdentifier) {
                return $this->userRepository->findByEmailOrUsername($userIdentifier);
            }),
            // ... rest of the parameters
        );
    }