Php Laravel 5.2 ACL如何使用相同的名称拥有多个权限并避免每个用户拥有一个角色

Php Laravel 5.2 ACL如何使用相同的名称拥有多个权限并避免每个用户拥有一个角色,php,laravel,permissions,acl,Php,Laravel,Permissions,Acl,好的,我正在尝试在Intranet上使用Laravel实现一个ACL,我遇到了一些权限快速增长失控的问题。首先,我得到的是: 我的五个表定义了我的用户、角色和权限,如下所示: tblIntranetUser UserID Name FirstName Username tblIntranetRoles RoleID RoleName Description tblIntranetPermissions PermissionID PermissionName Description tblI

好的,我正在尝试在Intranet上使用Laravel实现一个ACL,我遇到了一些权限快速增长失控的问题。首先,我得到的是:

我的五个表定义了我的用户、角色和权限,如下所示:

tblIntranetUser
UserID
Name
FirstName
Username

tblIntranetRoles
RoleID
RoleName
Description

tblIntranetPermissions
PermissionID
PermissionName
Description

tblIntranetRoles_Permissions
RoleID
PermissionID

tblIntranetUsers_Roles
UserID
RoleID
我还有AuthServiceProvider以及权限和角色模型:

class Permission extends Model
{
    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'tblIntranetPermissions';

    protected $primaryKey = 'PermissionID';

    public $timestamps = false;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['PermissionID', 'PermissionName', 'Description'];

    public function roles()
    {
        return $this->belongsToMany('App\Role', 'tblIntranetRoles_Permissions', 'PermissionID', 'RoleID');
    }

    public function detachAllRoles()
    {
        $roles = $this->roles;
        foreach($roles as $role){
           $role->permissions()->detach($this);
        }
    }
}

namespace App;

use Illuminate\Database\Eloquent\Model;
use App\User;

class Role extends Model
{
    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'tblIntranetRoles';

    protected $primaryKey = 'RoleID';

    public $timestamps = false;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['RoleID', 'RoleName', 'Description'];


    public function permissions()
    {
        return $this->belongsToMany('App\Permission', 'tblIntranetRoles_Permissions', 'RoleID', 'PermissionID');
    }

    public function givePermissionTo(Permission $permission)
    {
        return $this->permissions()->save($permission);
    }

    public function getUsers()
    {
        $users = User::orderBy('UserID')->get();
        $roleusers = collect();

        foreach($users as $user){
            if($user->hasRole($this->name)){
                $roleusers->push($user);
            }
        }
        return $roleusers;
    }

    public function detachAllUsers()
    {
        $users = $this->getUsers();
        foreach($users as $user){
            $user->roles()->detach($this);   
        }
    }

    public function detachAllPermissions()
    {
        $permissions = $this->permissions;
        foreach($permissions as $permission){
           $permission->roles()->detach($this);
        }
    }
}

namespace App\Providers;
use App\Report, App\Permission;
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [

    ];
    /**
     * Register any application authentication / authorization services.
     *
     * @param  \Illuminate\Contracts\Auth\Access\Gate  $gate
     * @return void
     */
    public function boot(GateContract $gate)
    {
        $this->registerPolicies($gate);

        foreach ($this->getPermissions() as $permission){

            $gate->before(function ($user) {
                if ($user->isSuperAdmin()) {
                    return true;
                }
            });

            $gate->define($permission->name, function($user) use ($permission){
                return $user->hasRole($permission->roles);
            });
        }
    }

    protected function getPermissions()
    {
        return Permission::with('roles')->get();
    }
}
因此,多亏了这一点,我能够创建各种角色并为它们分配权限,从而允许它们访问Intranet的某些部分以及查看某些报告。例如,我可以定义以下内容:

Role: Analyst
Access: Section 1, 2, 3
Reports: 1,15,41

Role: Developer
Access: All sections
Reports: All reports
如果每个分析师都能看到并访问相同的部分就好了。。。但事实并非如此。开发者也是如此。按照这个模型,它基本上意味着我需要为每个用户拥有一个角色,并为内联网上的每个可能元素拥有一个权限。考虑到大约有200个报告可用,以及大约30个用户,这就产生了很多“显示报告1”、“显示报告2”、“显示部分1”、“显示部分2”权限(Laravel通过名称标识权限)

所以,为了让事情变得更。。。我想,我一直在想,是否有一种方法可以让一个名为“show_report”的权限将reportID存储在另一个字段中,并避免每个用户都有一个角色。

我不确定这样做的“正确”方法,但您可以向一个透视表(可能是role_权限表)中添加额外的一行并使用它来存储有关权限的更具体数据。(例如,他们可以访问的部分)

查看此处以访问轴值:

这样,您就可以拥有“access_section”的单个权限,然后只需检查pivot即可查看他们可以访问哪些部分


(可能有更好或“适当”的方法来实现这一点)

行级安全性?这不是数据库吗?我正在尝试访问内部网的特定元素。您可以为
tblIntranetPermissionsLists
添加另一个数据结构和表,这将是
tblIntranetPermissions
的列表。它将有一个一对多的关系,比如1 TIPL可以引用M TIP。这实际上是一个相当不错的想法。它并没有消除每个用户需要一个角色的需要,但它仍然可以使权限更易于管理。我不知道为什么每个用户需要一个角色。角色是一组权限列表。权限列表是单个权限的集合。单一权限针对一个资源(页面、节、报告)。用户可以有0-M个角色。是吗?因为每个用户都有不同的权限集。因此,每个用户都需要为其定制自己的权限列表。。。因此,每个用户都需要自己的角色
$role = App\Role::find(1);

foreach ($role->permissions as $permission) {
    echo $permission->pivot->permission_settings; // [1,2,3]
}