Symfony2使用电子邮件而不是用户名进行身份验证/登录

6
我今天尝试使用Symfony2创建一个登录表单,用户可以使用他们的电子邮件地址和密码进行登录。我遇到了许多问题,最终意识到只有在我的AdminUser实体类中有一个$username属性时才能正常工作。我已经尽可能地使用电子邮件代替用户名,所以请有人解释为什么需要$username或者我哪里做错了吗?此外,在我的login.html.twig文件中,我仍在使用_username而不是_email,是否有任何区别?下面是我的代码(我删除了一些不适用的getter和setter):

AdminUser实体:

namespace XXX\WebsiteBundle\Entity;

use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as ORM;

/**
* AdminUser
*
* @ORM\Table(name="admin_user",indexes={@ORM\Index(name="indexes", columns={"deleted"})})
* @ORM\Entity
* @ORM\HasLifecycleCallbacks()
*/
class AdminUser implements UserInterface
{
/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="name", type="string", length=45)
 */
private $name;

/**
 * @var string
 *
 * @ORM\Column(name="email", type="string", length=45, unique=true)
 */
private $email;

/**
 * @var string
 *
 * @ORM\Column(name="salt", type="string", length=255)
 */
private $salt;

/**
 * @var string
 *
 * @ORM\Column(name="password", type="string", length=255)
 */
private $password;

/**
 * @var integer
 *
 * @ORM\Column(name="enabled", type="integer", options={"default" = 0})
 */
private $enabled;

/**
 * @var string[] $roles
 *
 * @ORM\Column(name="roles", type="array")
 */
private $roles = array();

private $username;


/**
 * Gets the username.
 *
 * @return string The username.
 */
public function getUsername()
{
    return $this->email;
}

/**
 * Erases the user credentials.
 */
public function eraseCredentials()
{

}


/**
 * Returns the roles granted to the user.
 *
 * <code>
 * public function getRoles()
 * {
 *     return array('ROLE_USER');
 * }
 * </code>
 *
 * Alternatively, the roles might be stored on a ``roles`` property,
 * and populated in any number of different ways when the user object
 * is created.
 *
 * @return Role[] The user roles
 */
public function getRoles() {
    return $this -> roles;
}

/**
 * Set the roles of the user
 *
 * @var string[] $roles
 *
 * @return \XXX\WebsiteBundle\Entity\User this
 */
public function setRoles(array $roles) {
    $this -> roles = $roles;

    return $this;
}



} 

我的security.yml文件如下:

jms_security_extra: secure_all_services: false expressions: true

这个文件用于设置安全性相关的配置,其中jms_security_extra是一个插件,在这个文件中,secure_all_services设置为false表示不对所有服务进行安全控制,而expressions设置为true则表示启用表达式语言来进行安全控制。
security:
encoders:
    XXX\WebsiteBundle\Entity\AdminUser: sha512

role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

providers:
    main_provider:
        entity: { class: XXX\WebsiteBundle\Entity\AdminUser, property: email }

firewalls:
    dev:
        pattern:  ^/(_(profiler|wdt)|css|images|js)/
        security: false

    admin_firewall:
        pattern:  ^/admin.*
        anonymous: ~
        form_login:
            login_path:  /admin/login
            check_path:  /admin/login_check

access_control:
    - { path: ^/admin/login.*, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin.*, roles: ROLE_ADMIN } 

你必须在AdminUser中拥有一个getUsername()方法,只是为了满足用户界面的要求。但它可以像你现在这样返回电子邮件。属性:email应该是你所需要做的全部。你可以查看EntityUserProvider类来验证发生了什么。也许从头开始安装?有时我在解决问题时会搞砸事情。 - Cerad
4个回答

12

我猜你应该通过以下方式更改电子邮件的属性,同时你可以通过更改“_username”参数为任何你想要的内容来实现:

entity:
            entity:
                class:               SecurityBundle:User
                property:            username

并且

firewalls
    form_login:
        username_parameter: _username

也许你应该看一下安全配置文档


2
对我来说没问题,唯一剩下的“拼图”是由于UserInterface接口而留下的getUsername()方法。 - Cesar
1
在security.yml文件中,firewalls -> main -> form_login下的username_parameter应设置为email,并且相应的输入框名称应为'email'。 - khaled_webdev

2
firewalls:
 main:
  form_login: 
    username_parameter: _email

您的代码全部正确,您只需要在security.yml文件中进行一些小改动。只需添加username_parameter即可。


0

这种方法有点hackish,但是你可以在注册表单中删除用户名字段,并在用户实体中执行以下操作:

public function setEmail($email) 
{
    $this->email = $email;
    $this->username = $email;
}

1
是的,我想是这样的,但是我正在努力学习最佳实践并防止被黑客攻击。我找到了这个页面 - http://symfony.com/doc/current/cookbook/security/entity_provider.html#authenticating-someone-with-a-custom-entity-provider 我需要创建一个AdminUserRepository吗? - user1961082

0

尝试使用FOSUserBundle

它具有默认功能特性,使用户能够使用其用户名或电子邮件字段登录。


3
FOSUserBundle 不支持仅使用电子邮件登录,它支持仅用户名登录,如果配置了则支持用户名或电子邮件登录。我只是想向那些寻求答案的人明确这一点。 - Twifty
如果问题是关于实现用户身份验证的不同方式,那么这将是一个有效的答案。但是用户的问题与提到的捆绑包无关。 - Evren Yurtesen

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