权限管理是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/');
?>
系统特点与优势
- 灵活的权限控制:支持菜单权限和操作权限的精细控制
- 多层级结构:支持无限层级的权限和菜单结构
- 中间件验证:使用中间件统一处理权限验证逻辑
- 动态菜单生成:根据用户权限动态生成导航菜单
- 易于扩展:模块化设计,方便添加新的权限控制点
- ThinkPHP最佳实践:充分利用ThinkPHP 6.x的新特性
实际应用建议
这个权限管理系统可以应用于多种场景:
- 企业后台管理系统:根据不同部门角色分配不同权限
- 电商平台:区分管理员、运营、客服等角色权限
- SaaS应用:为不同客户分配不同的功能权限
- 内容管理系统:控制编辑、审核、发布等权限
进一步优化方向
要使这个权限管理系统更加完善,可以考虑以下优化:
- 添加操作日志记录,跟踪用户权限使用情况
- 实现数据权限控制,限制用户只能访问特定范围的数据
- 添加权限缓存机制,提高权限验证性能
- 实现权限导入导出功能,方便权限配置迁移
- 添加权限模板功能,快速创建角色权限组
总结
通过本教程,我们实现了一个基于ThinkPHP 6.x的完整RBAC权限管理系统。这个系统包含了用户管理、角色管理、权限管理和动态菜单生成等核心功能,采用了中间件进行统一的权限验证。
该系统设计遵循了ThinkPHP的最佳实践,充分利用了模型关联、中间件、验证器等特性,代码结构清晰,易于维护和扩展。您可以根据实际项目需求,在此基础上进行进一步的定制和优化。
掌握权限管理系统的实现对于开发企业级应用至关重要,这个教程为您提供了一个坚实的基础,帮助您构建安全、灵活的权限控制系统。

