silex symfony 学说 ORM 多对多:登录时的 getRoles 返回空列表

头晕

你好 Silex(和 Symfony)专家,

我需要通过 Doctrine /ORM 实现数据库身份验证用户/角色模型。

这是我的 silex 作曲家设置:

"require": {
    "silex/web-profiler": "^2.0",
    "monolog/monolog": "1.13.*",
    "symfony/twig-bridge": "^3.2",
    "symfony/monolog-bridge": "^3.2",
    "symfony/console": "^3.2",
    "symfony/yaml": "^3.2",
    "symfony/security-bundle": "^3.2",
    "doctrine/orm": "^2.5",
    "dflydev/doctrine-orm-service-provider": "^2.0",
    "symfony/form": "^3.2",
    "symfony/validator": "^3.2",
    "symfony/config": "^3.2",
    "symfony/doctrine-bridge": "^3.2",
    "doctrine/migrations": "^1.5"
},

用户可以注册。注册用户可以登录和注销。非注册访问者具有匿名角色。

symfony 分析器正在工作,所以我可以看到安全状态(身份验证/授权)。我还跟踪 apache 日志文件中的 php 错误。

我从这里开始https://github.com/fredjuvaux/silex-orm-user-provider(来自数据库的用户,作为数组的角色)并尝试扩展它以通过多对多关系学说从数据库中获取用户角色。

有:

class MyUserController (different user actions like user,edit, register,... )
class MyUserManager implements UserProviderInterface (loadUserByUsername, ...)
class MyUserServiceProvider implements ServiceProviderInterface, ControllerProviderInterface,  BootableProviderInterface (controller routing and template setting)

ORM 实体是:

User:
/**
 * MyUser
 *
 * @Entity 
 * @Table(name="myuser")
 */
class MyUser implements UserInterface, \Serializable 
{
 ....

    /**
     * @ManyToMany(targetEntity="MyRole", inversedBy="users")
     *
     */
     private $roles;

...
     * Constructor.
     *
     * @param string $email
     */
    public function __construct($email)
    {
        $this->email = $email;
        $this->created = time();
        $this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
        $this->roles = new ArrayCollection();

    }

    ... 

      /**
     *
     * @return ArrayCollection list of the user's roles.
     */
    public function getRoles()
    {
      $result = $this->roles->toArray();   // throws error for login: 
      //  $result = $this->roles; // test   // thhrows error : null object
      dump($this->roles);
      //  $result = array("ROLE_USER", "ROLE_OTHER"); // static setting and 
works for login
      return $result;
    }
    ...
}


Roles (implements Roleinterface)
/**
 * MyRole
 * 
 * @Entity
 * @Table(name="myrole")
 */
class MyRole implements RoleInterface
{

     /**
     * @var string
     * @Column(name="role", type="string", length=20, unique=true)
     */
    private $role;

    /**
     * @ManyToMany(targetEntity="MyUser", mappedBy="roles")
     */
    private $users;

    ...
    /*
    *  methods for RoleInterface
    *  @return string|null A string representation of the role, or null
    */
    public function getRole()
    {
       $result = $this->role;
       return $result;
    }

}

当用户注册时,他为该会话获得 ROLE_USER 角色,身份验证和授权正常,并且在数据库中创建了一个用户。

然后我可以在控制器中为新用户分配新角色(“role_test1”、“role_test2”),填充多对多表 myuser_myrole(myuser_id myrole_id)。当我更改角色时,实体管理器会正确更新它们。

当我从 userController 访问用户实体来处理它时,我可以访问分配的角色:

// MyUserController.php
 $user = $em->getRepository('MyEntities\MyUser')->find($id);
 $roles= $user->getRoles()
 $role_length = count($roles);
 $role_list = array();
 for ($i=0; $i <$role_length ; $i++) 
 { 
      array_push($role_list,$roles[$i]->getRole());    // MyRole::getRole() prints out something to screen.
 }
 printf("<br> role-list:"); dump($role_list);

调用这个控制器会通过 MyRole::getRole() 打印出分配的角色,所以 ORM 访问在这里工作。

现在奇怪了:

我想用登录表单登录新用户。

当我使用

// MyUser::getRoles() 
  return $this->roles;

它抛出:

Argument 4 passed to Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken::__construct() must be of the type array, object given, 

好吧,也许是有道理的,因为 $roles 是一个 Doctrine ArrayCollection。

当我使用

// MyUser::getRoles() 
  return $this->roles->toArray();

我可以使用用户密码登录,但未通过身份验证(黄色状态)。转储角色后,我收到一个空数组 ArrayCollection。

roles:
ArrayCollection {#388 ▼
  -elements: []
}

UsernamePasswordToken 有一个空的角色数组。

When I use
// MyUser::getRoles() 
  return  array("ROLE_HELLO1", "ROLE_HELLO2");  // static role array with strings

我可以登录并使用以下角色进行身份验证:

角色

array:2 [▼
  0 => "ROLE_HELLO1"
  1 => "ROLE_HELLO2"
]

有关于 symfony 2 http://symfony.com/doc/2.0/cookbook/security/entity_provider.html 的旧文档(管理数据库中的角色),但它在 symfony3 中不起作用。

他们在这里使用

   //class User
   public function getRoles()
    {
        return $this->groups->toArray();
    }

    //class Group extends Role (not RoleInterface, old?)
    public function getRole()
    {
        return $this->role;
    }

用于用户管理的实际 symfony 文档没有展示如何使用存储在数据库中的角色。

总之:

登录名和用户/角色无法按预期工作:

MyUser::getRoles() 
  • 不通过学说 ORM 从数据库接收角色。

  • 必须返回用于登录的角色字符串数组。

  • 在另一个控制器中提供正确的角色关联。

问题:

(1) 这是 Silex 特有的问题吗?

(2) 如何正确使用它或解决方法的好链接/文档在哪里?

(3) LoadUserByUsername() 方法是否会干扰所有这些?

(4) 是否需要类 MyUserRepository extends EntityRepository {} 来执行查询并获取角色列表?

(5) 是否需要使用Role Hierarchy服务?

(6) “用户”和“角色”是否有特殊的命名约定(表名或类名)?

我发现许多帖子要求相同/相似,但它们在这里没有帮助。

谢谢你的帮助,我真的很坚持!

短剑

麦克斯

试试这个:

public function getRoles()
{
    return $this->roles->map(function (MyRole $role) {
        return $role->getRole();
    })->toArray();
}

您还应该检查关系是否正确保存在数据库中。如果MyUserMyRole之间存在ManyToMany关系,则必须确保该关系保存在两个实体中。

//class MyUser
public function addRole(MyRole $role)
{
    $this-roles->add($role);
    $role->users->add($user);
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章