发布日期:2023年12月15日
一、项目概述与技术选型
本教程将基于ThinkPHP6开发一个完整的RBAC(Role-Based Access Control)权限管理系统,主要功能包括:
- 多层级角色管理
- 细粒度权限控制
- 动态菜单生成
- 操作日志记录
- 数据权限控制
技术栈:ThinkPHP6 + MySQL + Redis + jQuery + Layui
二、环境准备与项目初始化
1. 环境要求
PHP ≥ 7.4
MySQL ≥ 5.7
Redis ≥ 5.0
Composer
2. 创建项目
composer create-project topthink/think tp6-rbac
cd tp6-rbac
composer require topthink/think-multi-app
3. 目录结构调整
app/
├── admin/ # 后台应用
│ ├── controller/
│ ├── model/
│ └── view/
├── common/ # 公共模块
│ ├── middleware/
│ └── service/
config/
├── admin/ # 后台配置
└── app.php # 核心配置
三、数据库设计与建模
1. RBAC核心表结构
# 管理员表
CREATE TABLE `admin` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '用户名',
`password` varchar(255) NOT NULL COMMENT '密码',
`salt` varchar(16) NOT NULL COMMENT '加密盐',
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态',
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 角色表
CREATE TABLE `role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL COMMENT '角色名称',
`description` varchar(255) DEFAULT NULL COMMENT '描述',
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 管理员角色关联表
CREATE TABLE `admin_role` (
`admin_id` int(11) NOT NULL COMMENT '管理员ID',
`role_id` int(11) NOT NULL COMMENT '角色ID',
PRIMARY KEY (`admin_id`,`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 权限表
CREATE TABLE `permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL COMMENT '权限名称',
`path` varchar(255) DEFAULT NULL COMMENT '路由路径',
`component` varchar(255) DEFAULT NULL COMMENT '组件路径',
`icon` varchar(32) DEFAULT NULL COMMENT '图标',
`type` tinyint(1) NOT NULL COMMENT '类型:1菜单 2按钮',
`parent_id` int(11) DEFAULT '0' COMMENT '父级ID',
`sort` int(11) DEFAULT '0' COMMENT '排序',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 角色权限关联表
CREATE TABLE `role_permission` (
`role_id` int(11) NOT NULL COMMENT '角色ID',
`permission_id` int(11) NOT NULL COMMENT '权限ID',
PRIMARY KEY (`role_id`,`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2. 模型定义
// app/admin/model/Admin.php
namespace appadminmodel;
use thinkModel;
class Admin extends Model
{
// 设置密码
public function setPasswordAttr($value)
{
$salt = random_str(16);
$this->setAttr('salt', $salt);
return md5(md5($value) . $salt);
}
// 关联角色
public function roles()
{
return $this->belongsToMany('Role', 'admin_role');
}
}
// app/admin/model/Role.php
class Role extends Model
{
// 关联权限
public function permissions()
{
return $this->belongsToMany('Permission', 'role_permission');
}
// 关联管理员
public function admins()
{
return $this->belongsToMany('Admin', 'admin_role');
}
}
四、核心功能实现
1. 权限验证中间件
// app/common/middleware/Auth.php
namespace appcommonmiddleware;
use thinkfacadeSession;
class Auth
{
public function handle($request, Closure $next)
{
$admin = Session::get('admin');
if (!$admin) {
return redirect('/admin/login');
}
// 获取当前请求路径
$path = $request->pathinfo();
// 超级管理员跳过验证
if ($admin['id'] == 1) {
return $next($request);
}
// 检查权限
$permissions = Session::get('admin.permissions');
if (!in_array($path, $permissions)) {
return json(['code' => 403, 'msg' => '无权访问']);
}
return $next($request);
}
}
2. 登录与权限初始化
// app/admin/controller/Login.php
public function doLogin()
{
$username = input('post.username');
$password = input('post.password');
$admin = Admin::where('username', $username)->find();
if (!$admin || $admin->password != md5(md5($password)) . $admin->salt) {
return json(['code' => 400, 'msg' => '用户名或密码错误']);
}
// 获取用户权限
$permissions = [];
foreach ($admin->roles as $role) {
foreach ($role->permissions as $permission) {
if ($permission->path) {
$permissions[] = $permission->path;
}
}
}
// 存储Session
Session::set('admin', [
'id' => $admin->id,
'username' => $admin->username,
'permissions' => array_unique($permissions)
]);
return json(['code' => 200, 'msg' => '登录成功']);
}
3. 动态菜单生成
// app/admin/controller/Index.php
public function getMenu()
{
$admin = Session::get('admin');
if ($admin['id'] == 1) {
// 超级管理员获取所有菜单
$menus = Permission::where('type', 1)
->order('sort', 'asc')
->select();
} else {
// 普通用户获取有权限的菜单
$menuIds = RolePermission::whereIn('role_id', function($query) use ($admin) {
$query->table('admin_role')->where('admin_id', $admin['id'])->field('role_id');
})
->column('permission_id');
$menus = Permission::where('type', 1)
->whereIn('id', $menuIds)
->order('sort', 'asc')
->select();
}
// 转换为树形结构
return json([
'code' => 200,
'data' => list_to_tree($menus->toArray())
]);
}
五、后台管理功能实现
1. 角色管理
// app/admin/controller/Role.php
public function save()
{
$data = input('post.');
if (empty($data['id'])) {
$role = Role::create($data);
} else {
$role = Role::find($data['id']);
$role->save($data);
}
// 更新权限
if (isset($data['permissions'])) {
$role->permissions()->detach();
$role->permissions()->attach($data['permissions']);
}
return json(['code' => 200, 'msg' => '操作成功']);
}
2. 权限树形展示
// app/admin/controller/Permission.php
public function tree()
{
$list = Permission::order('sort', 'asc')->select();
return json([
'code' => 200,
'data' => list_to_tree($list->toArray())
]);
}
3. 管理员分配角色
// app/admin/controller/Admin.php
public function setRoles()
{
$adminId = input('post.admin_id');
$roleIds = input('post.role_ids/a', []);
$admin = Admin::find($adminId);
$admin->roles()->detach();
$admin->roles()->attach($roleIds);
return json(['code' => 200, 'msg' => '操作成功']);
}
六、安全与性能优化
1. 安全防护措施
- 密码加盐加密存储
- CSRF防御机制
- XSS过滤
- SQL注入防护
- 操作日志审计
2. 性能优化方案
// 使用Redis缓存权限数据
public function getAdminPermissions($adminId)
{
$key = "admin:permissions:{$adminId}";
$permissions = Redis::get($key);
if (!$permissions) {
// 数据库查询逻辑...
Redis::set($key, json_encode($permissions), 3600);
}
return json_decode($permissions, true);
}
七、项目部署与扩展
1. 生产环境部署
# 优化配置
php think optimize:route
php think optimize:schema
# 设置目录权限
chmod -R 755 runtime
chown -R www:www .
2. 扩展方向
- 集成JWT实现API鉴权
- 开发数据权限控制模块
- 实现多租户SaaS支持
- 添加操作日志分析功能
八、总结
通过本教程,我们完成了:
- 基于ThinkPHP6的完整RBAC系统架构
- 角色与权限的多对多关系设计
- 动态菜单与权限验证的实现
- 企业级后台管理功能开发
该系统可直接应用于实际项目开发,或作为二次开发的基础框架。