Laravel中RBAC权限控制核心技术要点

2017/3/29 posted in  LARAVEL

SQL设计如下

DROP SCHEMA IF EXISTS `mydb` ;
-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`admin`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`admin` ;
CREATE TABLE IF NOT EXISTS `mydb`.`admin` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(16) NOT NULL,
  `password` VARCHAR(255) NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;
CREATE UNIQUE INDEX `username_UNIQUE` ON `mydb`.`admin` (`username` ASC);
  
-- -----------------------------------------------------
-- Table `mydb`.`role`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`role` ;
CREATE TABLE IF NOT EXISTS `mydb`.`role` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(10) NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;
CREATE UNIQUE INDEX `name_UNIQUE` ON `mydb`.`role` (`name` ASC);
  
-- -----------------------------------------------------
-- Table `mydb`.`role_admin`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`role_admin` ;
CREATE TABLE IF NOT EXISTS `mydb`.`role_admin` (
  `admin_id` INT UNSIGNED NOT NULL,
  `role_id` INT UNSIGNED NOT NULL)
ENGINE = InnoDB;
  
-- -----------------------------------------------------
-- Table `mydb`.`permission`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`permission` ;
CREATE TABLE IF NOT EXISTS `mydb`.`permission` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(10) NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;
CREATE UNIQUE INDEX `name_UNIQUE` ON `mydb`.`permission` (`name` ASC);
  
-- -----------------------------------------------------
-- Table `mydb`.`role_permission`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`role_permission` ;
CREATE TABLE IF NOT EXISTS `mydb`.`role_permission` (
  `role_id` INT UNSIGNED NOT NULL,
  `permission_id` INT UNSIGNED NOT NULL)
ENGINE = InnoDB;

管理员模型

public function roles()
{
    return $this->belongsToMany('App\Role', 'role_admin', 'admin_id', 'role_id');
}
public function hasRole($roleName)
{
    foreach($this->roles()->get() as $role) {
        if ($role->name == $roleName) {
            return true;
        }
    }
    return false;
}
public function hasPermission($permissionName)
{
    foreach($this->roles()->get() as $role) {
        foreach($role->permissions as $permission) {
            if ($permission->name == $permissionName) {
                return true;
            }
        }
    }
    return false;
}

角色模型

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
    //
    protected $table = 'role';
    protected $fillable = ['name', 'display_name'];
    protected static $list = null;
    public static function getList($refresh = false)
    {
        if ($refresh || is_null(self::$list)) {
            self::$list = static::with('permissions')->get();
        }
        return self::$list;
    }
    public static function getById($roleId)
    {
        $key = static::getList()->search(function($role) use ($roleId) {
            return $role->id == $roleId;
        });
        return $key ? static::getList()->get($key) : null;
    }
    public function permissions()
    {
        return $this->belongsToMany('App\Permission', 'role_permission', 'role_id', 'permission_id');
    }
}

权限模型

<?php
namespace App;
use App\Role;
use Illuminate\Database\Eloquent\Model;
class Permission extends Model
{
    //
    protected $table = 'permission';
    protected $fillable = ['name', 'display_name'];
    public function role()
    {
        foreach(Role::getList() as $role) {
            foreach($role->permissions as $permission) {
                if ($permission->id == $this->id) {
                    return $role;
                }
            }
        }
        return false;
    }
}