Symfony 4 EasyAdminBundle:纯密码的编码和保存问题

Posted

技术标签:

【中文标题】Symfony 4 EasyAdminBundle:纯密码的编码和保存问题【英文标题】:Symfony 4 EasyAdminBundle: Problem with encoding and saving of Plain Password 【发布时间】:2020-06-21 14:09:32 【问题描述】:

这是我使用 Symfony 的第一步。我尝试在 Symfony 4.4 中使用 Easyadmin Bundle 实现简单的用户管理。我按照 symfony.com 上的教程进行操作,其中大部分工作正常(注册表单、后端登录、后端安全、数据库中用户的后端列表)。

我的问题是在 Easyadmin 后端创建和更新用户。当我尝试创建新用户时,我看到了正确的字段,我确实输入了一些数据,如果我单击“保存更改”,则会引发以下错误:

An exception occurred while executing 'INSERT INTO app_users (username, email, roles, password, is_active) VALUES (?, ?, ?, ?, ?)' with params ["testname", "test@example.com", "a:1:i:0;s:9:\"ROLE_USER\";", null, 1]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'password' cannot be null

“密码”列不能为空很清楚:我需要为它提供一些编码的密码字符串。

我认为我输入的纯密码字段中的数据没有被我的用户实体中的 setPassword() 方法编码和/或处理。

据我了解一些 SO 答案和 Symfony 文档,它应该可以自动运行!?我不知道。我试图创建一个扩展 EasyAdminController 的 AdminController 并将其挂接到用户实体的持久化中的某个位置,但我无法让它工作。 (类似这样的:https://***.com/a/54749433)

如何处理/编码保存到数据库密码字段的普通密码?


用户实体:

// /src/Entity/User.php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;

/**
 * @ORM\Table(name="app_users")
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @UniqueEntity("username")
 * @UniqueEntity("email")
 */
class User implements AdvancedUserInterface, \Serializable

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=254, unique=true)
     * @Assert\NotBlank(groups="edit")
     */
    private $username;

    /**
     * @ORM\Column(type="string", length=254, unique=true)
     * @Assert\NotBlank()
     * @Assert\Email(groups="edit")
     */
    private $email;

    /**
     * @ORM\Column(type="array")
     */
    private $roles;

    /**
     * @Assert\Length(max=4096)
     */
    private $plainPassword;

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

    /**
     * @ORM\Column(name="is_active", type="boolean")
     */
    private $isActive;

    public function __construct()
        $this->roles = array('ROLE_USER');
        $this->isActive = true;
    

    public function getId()
        return $this->id;
    

    public function getUsername()
        return $this->username;
    

    public function setUsername($username)
        $this->username = $username;
    

    public function getEmail()
        return $this->email;
    

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

    public function getIsActive()
        return $this->isActive;
    

    public function setIsActive($is_active)
        $this->isActive = $is_active;
    

    public function getRoles()
        return $this->roles;
    

    public function setRoles($roles)
        $roles[] = 'ROLE_USER';
        $this->roles = $roles;
    

    public function getPlainPassword()
        return $this->plainPassword;
    

    public function setPlainPassword($password)
        $this->plainPassword = $password;
    

    public function getPassword()
    
        return $this->password;
    

    public function setPassword($password)
        $this->password = $password;
    

    public function getSalt()
        return null;
    

    public function eraseCredentials()

    public function isAccountNonExpired()
        return true;
    

    public function isAccountNonLocked()
        return true;
    

    public function isCredentialsNonExpired()
        return true;
    

    public function isEnabled()
        return $this->isActive;
    

    /** @see \Serializable::serialize() */
    public function serialize()
        return serialize(array(
            $this->id,
            $this->username,
            $this->email,
            $this->password,
            $this->isActive,
        ));
    

    /** @see \Serializable::unserialize() */
    public function unserialize($serialized)
        list (
            $this->id,
            $this->username,
            $this->email,
            $this->password,
            $this->isActive,
        ) = unserialize($serialized, array('allowed_classes' => false));
    

Security.yaml:

# /config/packages/security.yaml
security:
    encoders:
        App\Entity\User:
            algorithm: bcrypt
    providers:
        users_in_memory:  memory: null 
        our_db_provider:
            entity:
                class: App\Entity\User
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            anonymous: true
            pattern: ^/
            provider: our_db_provider
            form_login:
                login_path: login
                check_path: login
                default_target_path: account
                always_use_default_target_path: true
                csrf_token_generator: security.csrf.token_manager
            logout:
                path: /logout
                target: /login
    access_control:
        -  path: ^/admin, roles: ROLE_ADMIN 
        -  path: ^/account, roles: ROLE_USER 
        -  path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY 
        -  path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY 
        -  path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY 

Easyadmin.yaml:

# /config/packages/easy_admin.yaml
easy_admin:
    design:
        menu:
            -  entity: User, label: 'Benutzerverwaltung', icon: 'user' 
    entities:
        User:
            class: App\Entity\User
            label: 'Benutzer'
            password_encoding:  algorithm: 'bcrypt', cost: 12 
            form:
                form_options:  validation_groups: ['Default'] 
                fields:
                    -  type: 'group', icon: 'address-card', label: 'Informationen', css_class: 'col-lg-6' 
                    - username
                    - email
                    -  type: 'group', icon: 'user-shield', label: 'Rechteverwaltung', css_class: 'col-lg-6' 
                    -  property: 'is_active', type: 'checkbox' 
                    -  property: 'roles', type: 'choice', type_options:  multiple: true, choices:  'ROLE_USER': 'ROLE_USER', 'ROLE_ADMIN': 'ROLE_ADMIN'   
                    -  type: 'group', icon: 'user-lock', label: 'Passwort', css_class: 'col-lg-6' 
                    -  property: 'plainPassword', type: 'text', type_options:  required: false  

【问题讨论】:

【参考方案1】:

我现在可以回答我自己的问题了:

解决方案:我只是忘记在 Easyadmin 路由中引用控制器:

# config/routes/easy_admin.yaml
easy_admin_bundle:
    resource: 'App\Controller\AdminController'
    prefix: /admin
    type: annotation

这里是每个有相同问题的人的完整控制器:

// src/Controller/AdminController.php
namespace App\Controller;

use App\Entity\User;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use EasyCorp\Bundle\EasyAdminBundle\Controller\EasyAdminController;

class AdminController extends EasyAdminController

    private $passwordEncoder;

    public function __construct(UserPasswordEncoderInterface $passwordEncoder)
    
        $this->passwordEncoder = $passwordEncoder;
    

    private function encodeUserPlainPassword($user)
    
        $plainPassword = $user->getPlainPassword();

        if (!empty($plainPassword)) 
            $encoded = $this->passwordEncoder->encodePassword($user, $plainPassword);
            $user->setPassword($encoded);
        
    

    public function persistEntity($user)
    
        $this->encodeUserPlainPassword($user);
        parent::persistEntity($user);
    

    public function updateEntity($user)
    
        $this->encodeUserPlainPassword($user);
        parent::updateEntity($user);
    

【讨论】:

以上是关于Symfony 4 EasyAdminBundle:纯密码的编码和保存问题的主要内容,如果未能解决你的问题,请参考以下文章

FOSUserBundle 在 EasyAdminBundle 中管理((“用户”实体必须使用“类”选项定义其关联的 Doctrine 实体类))Symfony

CKEditor 未与 easyadmin 集成显示

EasyAdminBundle:验证不适用于 CKEditorType

使用 FOS 为 EasyAdminBundle 设置安全性

EasyAdminBundle NumberField 是舍入纬度和经度小数

easyadmin 实体字段的动态自定义选择