ThinkPHP多层级权限管理系统实现教程 – RBAC权限控制与最佳实践

2025-08-26 0 903

权限管理是Web应用中的核心功能之一。本文将详细介绍如何使用ThinkPHP 6.x框架实现一个完整的RBAC(基于角色的权限控制)系统,包含用户、角色、权限的多层级管理。

系统设计思路

我们将创建一个包含以下核心功能的权限管理系统:

  • 用户管理:系统用户账户的CRUD操作
  • 角色管理:定义不同角色并分配权限
  • 权限管理:创建系统操作权限点
  • 菜单管理:动态生成权限控制的导航菜单
  • 中间件验证:使用中间件进行权限验证

数据库设计

数据表结构

-- 用户表
CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL DEFAULT '' COMMENT '用户名',
  `password` varchar(255) NOT NULL DEFAULT '' COMMENT '密码',
  `email` varchar(100) DEFAULT '' COMMENT '邮箱',
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态:1正常,0禁用',
  `create_time` int(11) DEFAULT NULL COMMENT '创建时间',
  `update_time` int(11) DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

-- 角色表
CREATE TABLE `role` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL DEFAULT '' COMMENT '角色名称',
  `description` varchar(255) DEFAULT '' COMMENT '角色描述',
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态:1正常,0禁用',
  `create_time` int(11) DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';

-- 权限表
CREATE TABLE `permission` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL DEFAULT '' COMMENT '权限名称',
  `path` varchar(100) NOT NULL DEFAULT '' COMMENT '权限路径',
  `type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '类型:1菜单,2操作',
  `pid` int(11) NOT NULL DEFAULT '0' COMMENT '父级ID',
  `sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序',
  `icon` varchar(50) DEFAULT '' COMMENT '图标',
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态:1正常,0禁用',
  `create_time` int(11) DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='权限表';

-- 用户角色关联表
CREATE TABLE `user_role` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL COMMENT '用户ID',
  `role_id` int(11) NOT NULL COMMENT '角色ID',
  `create_time` int(11) DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  KEY `role_id` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户角色关联表';

-- 角色权限关联表
CREATE TABLE `role_permission` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `role_id` int(11) NOT NULL COMMENT '角色ID',
  `permission_id` int(11) NOT NULL COMMENT '权限ID',
  `create_time` int(11) DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `role_id` (`role_id`),
  KEY `permission_id` (`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色权限关联表';
    

核心功能实现

1. 模型定义

用户模型 (app/model/User.php)

<?php
namespace appmodel;

use thinkModel;
use thinkmodelconcernSoftDelete;

class User extends Model
{
    use SoftDelete;
    
    protected $name = 'user';
    protected $autoWriteTimestamp = true;
    
    // 设置密码加密
    public function setPasswordAttr($value)
    {
        return password_hash($value, PASSWORD_DEFAULT);
    }
    
    // 用户角色关联
    public function roles()
    {
        return $this->belongsToMany('Role', 'UserRole');
    }
    
    // 检查用户是否有指定权限
    public function hasPermission($permissionPath)
    {
        // 超级管理员拥有所有权限
        if ($this->id === 1) {
            return true;
        }
        
        $roles = $this->roles()->with('permissions')->select();
        
        foreach ($roles as $role) {
            foreach ($role->permissions as $permission) {
                if ($permission->path === $permissionPath && $permission->status === 1) {
                    return true;
                }
            }
        }
        
        return false;
    }
}
?>
    

角色模型 (app/model/Role.php)

<?php
namespace appmodel;

use thinkModel;

class Role extends Model
{
    protected $name = 'role';
    protected $autoWriteTimestamp = true;
    
    // 角色权限关联
    public function permissions()
    {
        return $this->belongsToMany('Permission', 'RolePermission');
    }
    
    // 获取角色权限ID数组
    public function getPermissionIds()
    {
        return $this->permissions()->column('permission_id');
    }
}
?>
    

权限模型 (app/model/Permission.php)

<?php
namespace appmodel;

use thinkModel;

class Permission extends Model
{
    protected $name = 'permission';
    protected $autoWriteTimestamp = true;
    
    // 获取树形权限结构
    public static function getTree($pid = 0)
    {
        $permissions = self::where('pid', $pid)
            ->where('status', 1)
            ->order('sort', 'asc')
            ->select();
        
        if ($permissions->isEmpty()) {
            return [];
        }
        
        foreach ($permissions as &$permission) {
            $children = self::getTree($permission->id);
            if (!empty($children)) {
                $permission->children = $children;
            }
        }
        
        return $permissions->toArray();
    }
}
?>
    

2. 权限验证中间件

(app/middleware/PermissionCheck.php)

<?php
namespace appmiddleware;

use thinkfacadeRequest;
use thinkfacadeSession;

class PermissionCheck
{
    public function handle($request, Closure $next)
    {
        // 排除登录页面和登录操作
        $excludeRoutes = [
            'admin/login/index',
            'admin/login/login',
            'admin/login/logout'
        ];
        
        $currentRoute = strtolower($request->controller() . '/' . $request->action());
        
        if (in_array($currentRoute, $excludeRoutes)) {
            return $next($request);
        }
        
        // 检查用户是否登录
        $user = Session::get('admin_user');
        if (!$user) {
            return redirect('/admin/login/index');
        }
        
        // 检查权限
        $permissionPath = strtolower($request->module() . '/' . $request->controller() . '/' . $request->action());
        
        if (!$user->hasPermission($permissionPath)) {
            if ($request->isAjax()) {
                return json(['code' => 403, 'msg' => '没有权限操作']);
            } else {
                return view('admin@public/error', ['msg' => '没有权限操作']);
            }
        }
        
        return $next($request);
    }
}
?>
    

3. 权限管理控制器

(app/controller/admin/PermissionController.php)

<?php
namespace appcontrolleradmin;

use appBaseController;
use appmodelPermission;
use thinkfacadeView;

class PermissionController extends BaseController
{
    // 权限列表
    public function index()
    {
        $permissions = Permission::getTree();
        View::assign('permissions', $permissions);
        return View::fetch();
    }
    
    // 添加权限
    public function add()
    {
        if ($this->request->isPost()) {
            $data = $this->request->post();
            
            $validate = new appvalidatePermission();
            if (!$validate->check($data)) {
                return json(['code' => 0, 'msg' => $validate->getError()]);
            }
            
            try {
                $permission = Permission::create($data);
                return json(['code' => 1, 'msg' => '添加成功']);
            } catch (Exception $e) {
                return json(['code' => 0, 'msg' => '添加失败: ' . $e->getMessage()]);
            }
        }
        
        $parentPermissions = Permission::where('pid', 0)
            ->where('status', 1)
            ->select();
        
        View::assign('parentPermissions', $parentPermissions);
        return View::fetch();
    }
    
    // 编辑权限
    public function edit($id)
    {
        $permission = Permission::find($id);
        if (!$permission) {
            return json(['code' => 0, 'msg' => '权限不存在']);
        }
        
        if ($this->request->isPost()) {
            $data = $this->request->post();
            
            $validate = new appvalidatePermission();
            if (!$validate->check($data)) {
                return json(['code' => 0, 'msg' => $validate->getError()]);
            }
            
            try {
                $permission->save($data);
                return json(['code' => 1, 'msg' => '更新成功']);
            } catch (Exception $e) {
                return json(['code' => 0, 'msg' => '更新失败: ' . $e->getMessage()]);
            }
        }
        
        $parentPermissions = Permission::where('pid', 0)
            ->where('status', 1)
            ->where('id', '', $id)
            ->select();
        
        View::assign([
            'permission' => $permission,
            'parentPermissions' => $parentPermissions
        ]);
        
        return View::fetch();
    }
    
    // 删除权限
    public function delete($id)
    {
        $permission = Permission::find($id);
        if (!$permission) {
            return json(['code' => 0, 'msg' => '权限不存在']);
        }
        
        // 检查是否有子权限
        $childCount = Permission::where('pid', $id)->count();
        if ($childCount > 0) {
            return json(['code' => 0, 'msg' => '请先删除子权限']);
        }
        
        try {
            $permission->delete();
            return json(['code' => 1, 'msg' => '删除成功']);
        } catch (Exception $e) {
            return json(['code' => 0, 'msg' => '删除失败: ' . $e->getMessage()]);
        }
    }
}
?>
    

4. 角色管理控制器

(app/controller/admin/RoleController.php)

<?php
namespace appcontrolleradmin;

use appBaseController;
use appmodelRole;
use appmodelPermission;
use thinkfacadeView;

class RoleController extends BaseController
{
    // 角色列表
    public function index()
    {
        $roles = Role::where('status', 1)->select();
        View::assign('roles', $roles);
        return View::fetch();
    }
    
    // 添加角色
    public function add()
    {
        if ($this->request->isPost()) {
            $data = $this->request->post();
            
            $validate = new appvalidateRole();
            if (!$validate->check($data)) {
                return json(['code' => 0, 'msg' => $validate->getError()]);
            }
            
            try {
                $role = Role::create($data);
                
                // 分配权限
                if (!empty($data['permission_ids'])) {
                    $role->permissions()->saveAll($data['permission_ids']);
                }
                
                return json(['code' => 1, 'msg' => '添加成功']);
            } catch (Exception $e) {
                return json(['code' => 0, 'msg' => '添加失败: ' . $e->getMessage()]);
            }
        }
        
        // 获取所有权限
        $permissions = Permission::getTree();
        View::assign('permissions', $permissions);
        return View::fetch();
    }
    
    // 编辑角色
    public function edit($id)
    {
        $role = Role::find($id);
        if (!$role) {
            return json(['code' => 0, 'msg' => '角色不存在']);
        }
        
        if ($this->request->isPost()) {
            $data = $this->request->post();
            
            $validate = new appvalidateRole();
            if (!$validate->check($data)) {
                return json(['code' => 0, 'msg' => $validate->getError()]);
            }
            
            try {
                $role->save($data);
                
                // 更新权限
                if (isset($data['permission_ids'])) {
                    $role->permissions()->detach();
                    if (!empty($data['permission_ids'])) {
                        $role->permissions()->saveAll($data['permission_ids']);
                    }
                }
                
                return json(['code' => 1, 'msg' => '更新成功']);
            } catch (Exception $e) {
                return json(['code' => 0, 'msg' => '更新失败: ' . $e->getMessage()]);
            }
        }
        
        // 获取所有权限
        $permissions = Permission::getTree();
        
        // 获取角色已有权限ID
        $rolePermissionIds = $role->getPermissionIds();
        
        View::assign([
            'role' => $role,
            'permissions' => $permissions,
            'rolePermissionIds' => $rolePermissionIds
        ]);
        
        return View::fetch();
    }
    
    // 删除角色
    public function delete($id)
    {
        $role = Role::find($id);
        if (!$role) {
            return json(['code' => 0, 'msg' => '角色不存在']);
        }
        
        // 检查是否有用户使用此角色
        $userCount = $role->users()->count();
        if ($userCount > 0) {
            return json(['code' => 0, 'msg' => '有用户使用此角色,无法删除']);
        }
        
        try {
            // 删除角色权限关联
            $role->permissions()->detach();
            $role->delete();
            
            return json(['code' => 1, 'msg' => '删除成功']);
        } catch (Exception $e) {
            return json(['code' => 0, 'msg' => '删除失败: ' . $e->getMessage()]);
        }
    }
}
?>
    

5. 动态菜单生成

创建菜单助手函数 (app/common.php)

<?php
// 获取用户有权限的菜单
function get_admin_menu($user)
{
    // 超级管理员获取所有菜单
    if ($user->id === 1) {
        $menus = appmodelPermission::where('type', 1)
            ->where('status', 1)
            ->order('sort', 'asc')
            ->select();
    } else {
        // 获取用户角色
        $roles = $user->roles;
        $permissionIds = [];
        
        foreach ($roles as $role) {
            $rolePermissionIds = $role->permissions()
                ->where('type', 1)
                ->where('status', 1)
                ->column('permission.id');
            
            $permissionIds = array_merge($permissionIds, $rolePermissionIds);
        }
        
        $permissionIds = array_unique($permissionIds);
        
        if (empty($permissionIds)) {
            return [];
        }
        
        $menus = appmodelPermission::where('id', 'in', $permissionIds)
            ->where('type', 1)
            ->where('status', 1)
            ->order('sort', 'asc')
            ->select();
    }
    
    return array_to_tree($menus->toArray());
}

// 数组转树形结构
function array_to_tree($list, $pk = 'id', $pid = 'pid', $child = 'children', $root = 0)
{
    $tree = [];
    $refer = [];
    
    foreach ($list as $key => $data) {
        $refer[$data[$pk]] = &$list[$key];
    }
    
    foreach ($list as $key => $data) {
        $parentId = $data[$pid];
        if ($root == $parentId) {
            $tree[] = &$list[$key];
        } else {
            if (isset($refer[$parentId])) {
                $parent = &$refer[$parentId];
                $parent[$child][] = &$list[$key];
            }
        }
    }
    
    return $tree;
}
?>
    

6. 中间件注册与使用

全局中间件注册 (app/middleware.php)

<?php
return [
    // 全局中间件
    appmiddlewarePermissionCheck::class,
];
?>
    

路由配置 (route/app.php)

<?php
use thinkfacadeRoute;

// 后台路由组
Route::group('admin', function () {
    // 登录路由
    Route::get('login/index', 'admin/Login/index');
    Route::post('login/login', 'admin/Login/login');
    Route::get('login/logout', 'admin/Login/logout');
    
    // 权限管理
    Route::get('permission/index', 'admin/Permission/index');
    Route::get('permission/add', 'admin/Permission/add');
    Route::post('permission/add', 'admin/Permission/add');
    Route::get('permission/edit/:id', 'admin/Permission/edit');
    Route::post('permission/edit/:id', 'admin/Permission/edit');
    Route::post('permission/delete/:id', 'admin/Permission/delete');
    
    // 角色管理
    Route::get('role/index', 'admin/Role/index');
    Route::get('role/add', 'admin/Role/add');
    Route::post('role/add', 'admin/Role/add');
    Route::get('role/edit/:id', 'admin/Role/edit');
    Route::post('role/edit/:id', 'admin/Role/edit');
    Route::post('role/delete/:id', 'admin/Role/delete');
    
    // 用户管理
    Route::get('user/index', 'admin/User/index');
    Route::get('user/add', 'admin/User/add');
    Route::post('user/add', 'admin/User/add');
    Route::get('user/edit/:id', 'admin/User/edit');
    Route::post('user/edit/:id', 'admin/User/edit');
    Route::post('user/delete/:id', 'admin/User/delete');
})->prefix('admin/');
?>
    

系统特点与优势

  1. 灵活的权限控制:支持菜单权限和操作权限的精细控制
  2. 多层级结构:支持无限层级的权限和菜单结构
  3. 中间件验证:使用中间件统一处理权限验证逻辑
  4. 动态菜单生成:根据用户权限动态生成导航菜单
  5. 易于扩展:模块化设计,方便添加新的权限控制点
  6. ThinkPHP最佳实践:充分利用ThinkPHP 6.x的新特性

实际应用建议

这个权限管理系统可以应用于多种场景:

  • 企业后台管理系统:根据不同部门角色分配不同权限
  • 电商平台:区分管理员、运营、客服等角色权限
  • SaaS应用:为不同客户分配不同的功能权限
  • 内容管理系统:控制编辑、审核、发布等权限

进一步优化方向

要使这个权限管理系统更加完善,可以考虑以下优化:

  1. 添加操作日志记录,跟踪用户权限使用情况
  2. 实现数据权限控制,限制用户只能访问特定范围的数据
  3. 添加权限缓存机制,提高权限验证性能
  4. 实现权限导入导出功能,方便权限配置迁移
  5. 添加权限模板功能,快速创建角色权限组

总结

通过本教程,我们实现了一个基于ThinkPHP 6.x的完整RBAC权限管理系统。这个系统包含了用户管理、角色管理、权限管理和动态菜单生成等核心功能,采用了中间件进行统一的权限验证。

该系统设计遵循了ThinkPHP的最佳实践,充分利用了模型关联、中间件、验证器等特性,代码结构清晰,易于维护和扩展。您可以根据实际项目需求,在此基础上进行进一步的定制和优化。

掌握权限管理系统的实现对于开发企业级应用至关重要,这个教程为您提供了一个坚实的基础,帮助您构建安全、灵活的权限控制系统

ThinkPHP多层级权限管理系统实现教程 - RBAC权限控制与最佳实践
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 thinkphp ThinkPHP多层级权限管理系统实现教程 – RBAC权限控制与最佳实践 https://www.taomawang.com/server/thinkphp/985.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务