Where to define security roles?

2019-07-12 13:21发布

问题:

I have an User and a Group Entity which both hold an array of roles.

Now I would like to keep the option open to modificate the roles, add them and so on.

Should I use constants in the classes for this or should I relate an OneToOne-relation to a table which keeps all the roles?

Best Regards, pus.dev

User <=> Role Group <=> Role

public function getRoles()
{
    $roles = $this->roles;

    foreach ($this->getGroups() as $group) {
        $roles = array_merge($roles, $group->getRoles());
    }

    // we need to make sure to have at least one role
    $roles[] = static::ROLE_DEFAULT;

    return array_unique($roles);
}

回答1:

How about creating a Roles table with ManyToOne relation to each user. One row of the Roles table would contain a role(string or constant int) and a user.

Alternatively you can create a Roles table and have a ManyToMany relation with the User table. Using this you could define roles dynamically, so you don't have to hardcode the possible roles.

In the OneToMany case you could retrieve the roles by writing such a function:

/** @OneToMany(...) */
/** $roles contains strings */
protected $roles;

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

OR

/** @OneToMany(...) */
/** $roles contains integers */
protected $roles;

public function getRoles() {
    $rolesArr = array(1 => 'ROLE_ADMIN', 2 => 'ROLE_USER', 3 => 'ROLE_EDITOR'); // you should refactor $rolesArr
    $retRoles = array();
    foreach($this->roles as $role) {
        $retRoles[] = $rolesArr[$role];
    }
    return $retRoles;
}

In the ManyToMany case you could retrieve the roles by writing such a function:

/** @ManyToMany(...) */
protected $roles;
// ...
public function getRoles() {
    $retRoles = array();
    // symfony2 requires a string array
    foreach($this->roles as $role) {
        $retRoles[] = $role->getName(); // or $retRoles[] = 'ROLE_' . $role->getName();
    }
    return $retRoles;
}

And dont forget that your User model must implement symfony's built-in User interface.

For group roles you can do this:

class Group
{
    /** @ManyToMany(...) */
    protected $roles;

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

class User
{
   /** @ORM\Column(...) */
   protected $group;

    /** @ManyToMany(...) */
    protected $roles;
    // ...

    public function getRoles() {
        $retRoles = array();
        // symfony2 requires a string array
        $roles = $this->roles->merge($this->group->getRoles());
        foreach($roles as $role) {
            $retRoles[] = $role->getName(); // or $retRoles[] = 'ROLE_' . $role->getName();
        }
        return $retRoles;
    }
}