ThinkPHP 6.x企业级RBAC权限管理系统开发实战教程

2025-09-25 0 266

发布日期:2024年1月18日 | 作者:ThinkPHP框架专家

本教程将深入讲解如何使用ThinkPHP 6.x框架开发一个完整的企业级RBAC(基于角色的权限控制)管理系统。

一、项目概述与技术栈选择

系统功能需求

  • 多角色用户权限管理
  • 动态菜单权限控制
  • 操作日志记录与审计
  • 数据权限隔离
  • API接口安全验证

技术架构选型

后端框架:ThinkPHP 6.1.x
数据库:MySQL 8.0
缓存:Redis 6.x
前端:LayUI + jQuery
API文档:Swagger
部署:Docker + Nginx

二、环境配置与框架安装

Composer安装ThinkPHP 6.x

# 创建新项目
composer create-project topthink/think tp-rbac-system

# 进入项目目录
cd tp-rbac-system

# 安装扩展依赖
composer require topthink/think-multi-app
composer require topthink/think-migration

多应用模式配置

// config/app.php
return [
    // 开启多应用模式
    'auto_multi_app'   => true,
    'app_express'      => true,
    
    // 默认应用
    'default_app'      => 'admin',
    // 默认时区
    'default_timezone' => 'Asia/Shanghai',
];

目录结构规划

tp-rbac-system/
├── app/
│   ├── admin/          # 后台管理应用
│   ├── api/           # API接口应用
│   └── common/        # 公共模块
├── config/
├── public/
├── runtime/
└── vendor/

三、数据库设计与模型创建

RBAC核心表结构

-- 用户表
CREATE TABLE `rbac_user` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `username` varchar(50) NOT NULL COMMENT '用户名',
    `password` varchar(255) NOT NULL COMMENT '密码',
    `realname` varchar(50) DEFAULT NULL COMMENT '真实姓名',
    `email` varchar(100) DEFAULT NULL COMMENT '邮箱',
    `mobile` varchar(20) DEFAULT NULL COMMENT '手机号',
    `status` tinyint(1) DEFAULT '1' COMMENT '状态:1正常 0禁用',
    `last_login_time` datetime DEFAULT NULL COMMENT '最后登录时间',
    `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
    `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

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

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

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

-- 角色权限关联表
CREATE TABLE `rbac_role_node` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `role_id` int(11) NOT NULL COMMENT '角色ID',
    `node_id` int(11) NOT NULL COMMENT '权限节点ID',
    `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    UNIQUE KEY `role_node` (`role_id`,`node_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色权限关联表';

模型类创建

<?php
// app/admin/model/User.php
namespace appadminmodel;

use thinkModel;
use thinkmodelconcernSoftDelete;

class User extends Model
{
    use SoftDelete;
    
    protected $table = 'rbac_user';
    protected $pk = 'id';
    protected $deleteTime = 'delete_time';
    
    // 自动时间戳
    protected $autoWriteTimestamp = true;
    protected $createTime = 'create_time';
    protected $updateTime = 'update_time';
    
    // 密码自动加密
    public function setPasswordAttr($value)
    {
        return password_hash($value, PASSWORD_DEFAULT);
    }
    
    // 关联角色
    public function roles()
    {
        return $this->belongsToMany('Role', 'rbac_user_role', 'role_id', 'user_id');
    }
}

// app/admin/model/Role.php
class Role extends Model
{
    protected $table = 'rbac_role';
    protected $pk = 'id';
    
    // 关联权限节点
    public function nodes()
    {
        return $this->belongsToMany('Node', 'rbac_role_node', 'node_id', 'role_id');
    }
    
    // 关联用户
    public function users()
    {
        return $this->belongsToMany('User', 'rbac_user_role', 'user_id', 'role_id');
    }
}

// app/admin/model/Node.php
class Node extends Model
{
    protected $table = 'rbac_node';
    protected $pk = 'id';
    
    // 获取树形结构
    public static function getTree($pid = 0)
    {
        $nodes = self::where('pid', $pid)
            ->where('status', 1)
            ->order('sort', 'asc')
            ->select();
        
        foreach ($nodes as &$node) {
            $node['children'] = self::getTree($node['id']);
        }
        
        return $nodes;
    }
}
?>

四、RBAC权限架构设计

权限验证服务类

<?php
// app/common/service/Permission.php
namespace appcommonservice;

use thinkfacadeSession;
use appadminmodelUser;

class Permission
{
    // 检查权限
    public static function check($node)
    {
        $user = Session::get('admin_user');
        if (!$user) {
            return false;
        }
        
        // 超级管理员拥有所有权限
        if ($user['id'] == 1) {
            return true;
        }
        
        $userModel = User::with(['roles.nodes'])->find($user['id']);
        $userNodes = [];
        
        foreach ($userModel->roles as $role) {
            foreach ($role->nodes as $node) {
                $userNodes[] = $node->path;
            }
        }
        
        return in_array($node, array_unique($userNodes));
    }
    
    // 获取用户菜单
    public static function getMenus()
    {
        $user = Session::get('admin_user');
        if (!$user) {
            return [];
        }
        
        $userModel = User::with(['roles.nodes'])->find($user['id']);
        $menuNodes = [];
        
        foreach ($userModel->roles as $role) {
            foreach ($role->nodes as $node) {
                if ($node->type == 1) { // 菜单类型
                    $menuNodes[] = $node->toArray();
                }
            }
        }
        
        return self::buildTree(array_unique($menuNodes, SORT_REGULAR));
    }
    
    // 构建菜单树
    private static function buildTree($nodes, $pid = 0)
    {
        $tree = [];
        foreach ($nodes as $node) {
            if ($node['pid'] == $pid) {
                $children = self::buildTree($nodes, $node['id']);
                if ($children) {
                    $node['children'] = $children;
                }
                $tree[] = $node;
            }
        }
        return $tree;
    }
}
?>

五、中间件与权限验证

权限验证中间件

<?php
// app/admin/middleware/Auth.php
namespace appadminmiddleware;

use thinkfacadeSession;
use appcommonservicePermission;

class Auth
{
    public function handle($request, Closure $next)
    {
        // 排除登录页面
        $allowUrl = ['admin/auth/login', 'admin/auth/logout'];
        $currentUrl = $request->controller() . '/' . $request->action();
        
        if (!in_array($currentUrl, $allowUrl)) {
            // 检查登录状态
            if (!Session::has('admin_user')) {
                return redirect('/admin/auth/login');
            }
            
            // 检查权限
            $node = strtolower($request->controller() . '/' . $request->action());
            if (!Permission::check($node)) {
                if ($request->isAjax()) {
                    return json(['code' => 403, 'msg' => '没有访问权限']);
                } else {
                    return view('admin@public/error', ['msg' => '没有访问权限']);
                }
            }
        }
        
        return $next($request);
    }
}

中间件注册配置

// app/admin/middleware.php
return [
    // 全局中间件
    appadminmiddlewareAuth::class,
    
    // 路由中间件别名
    'alias' => [
        'auth' => appadminmiddlewareAuth::class,
        'log'   => appadminmiddlewareOperationLog::class,
    ],
];

操作日志中间件

<?php
// app/admin/middleware/OperationLog.php
namespace appadminmiddleware;

use thinkfacadeSession;
use appadminmodelOperationLog as LogModel;

class OperationLog
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        
        // 记录操作日志
        if ($request->isPost() || $request->isDelete()) {
            $user = Session::get('admin_user');
            $logData = [
                'user_id'    => $user['id'] ?? 0,
                'username'   => $user['username'] ?? '',
                'ip'         => $request->ip(),
                'user_agent' => $request->header('user-agent'),
                'method'     => $request->method(),
                'path'       => $request->pathinfo(),
                'params'     => json_encode($request->param(), JSON_UNESCAPED_UNICODE),
                'create_time' => date('Y-m-d H:i:s')
            ];
            
            LogModel::create($logData);
        }
        
        return $response;
    }
}

六、后台管理模块实现

用户管理控制器

<?php
// app/admin/controller/User.php
namespace appadmincontroller;

use thinkfacadeRequest;
use appadminmodelUser as UserModel;
use appadminmodelRole as RoleModel;

class User extends Base
{
    // 用户列表
    public function index()
    {
        if (Request::isAjax()) {
            $page = Request::param('page', 1);
            $limit = Request::param('limit', 15);
            $keywords = Request::param('keywords', '');
            
            $where = [];
            if (!empty($keywords)) {
                $where[] = ['username|realname|email', 'like', "%{$keywords}%"];
            }
            
            $list = UserModel::with(['roles'])
                ->where($where)
                ->page($page, $limit)
                ->select();
                
            $total = UserModel::where($where)->count();
            
            return json([
                'code' => 0,
                'msg'  => 'success',
                'count' => $total,
                'data' => $list
            ]);
        }
        
        return view();
    }
    
    // 添加用户
    public function add()
    {
        if (Request::isPost()) {
            $data = Request::param();
            
            // 验证数据
            $validate = new appadminvalidateUser();
            if (!$validate->check($data)) {
                return json(['code' => 1, 'msg' => $validate->getError()]);
            }
            
            // 创建用户
            $user = UserModel::create($data);
            if ($user) {
                // 分配角色
                if (!empty($data['role_ids'])) {
                    $user->roles()->saveAll($data['role_ids']);
                }
                return json(['code' => 0, 'msg' => '添加成功']);
            } else {
                return json(['code' => 1, 'msg' => '添加失败']);
            }
        }
        
        // 获取角色列表
        $roles = RoleModel::where('status', 1)->select();
        $this->assign('roles', $roles);
        
        return view();
    }
    
    // 编辑用户
    public function edit($id)
    {
        $user = UserModel::with(['roles'])->find($id);
        if (!$user) {
            $this->error('用户不存在');
        }
        
        if (Request::isPost()) {
            $data = Request::param();
            
            // 如果密码为空,则不更新密码
            if (empty($data['password'])) {
                unset($data['password']);
            }
            
            if ($user->save($data)) {
                // 更新角色
                if (isset($data['role_ids'])) {
                    $user->roles()->detach();
                    $user->roles()->saveAll($data['role_ids']);
                }
                return json(['code' => 0, 'msg' => '更新成功']);
            } else {
                return json(['code' => 1, 'msg' => '更新失败']);
            }
        }
        
        $roles = RoleModel::where('status', 1)->select();
        $userRoles = array_column($user->roles->toArray(), 'id');
        
        $this->assign([
            'user' => $user,
            'roles' => $roles,
            'userRoles' => $userRoles
        ]);
        
        return view();
    }
}

基础控制器类

<?php
// app/admin/controller/Base.php
namespace appadmincontroller;

use thinkController;
use thinkfacadeSession;
use appcommonservicePermission;

class Base extends Controller
{
    protected function initialize()
    {
        parent::initialize();
        
        // 获取当前用户信息
        $user = Session::get('admin_user');
        $this->assign('admin_user', $user);
        
        // 获取菜单
        $menus = Permission::getMenus();
        $this->assign('menus', $menus);
        
        // 当前控制器和方法
        $this->assign('controller', $this->request->controller());
        $this->assign('action', $this->request->action());
    }
    
    // 成功跳转
    protected function success($msg = '操作成功', $url = null)
    {
        if (is_null($url)) {
            $url = $this->request->isAjax() ? '' : 'javascript:history.back()';
        }
        
        return json(['code' => 0, 'msg' => $msg, 'url' => $url]);
    }
    
    // 错误跳转
    protected function error($msg = '操作失败', $url = null)
    {
        if (is_null($url)) {
            $url = $this->request->isAjax() ? '' : 'javascript:history.back()';
        }
        
        return json(['code' => 1, 'msg' => $msg, 'url' => $url]);
    }
}

七、前后端分离实践

API应用配置

// app/api/controller/Base.php
namespace appapicontroller;

use thinkController;
use thinkfacadeRequest;

class Base extends Controller
{
    protected $userInfo = [];
    
    protected function initialize()
    {
        // 跨域设置
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Headers: Authorization, Content-Type, Token');
        header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
        
        if (Request::isOptions()) {
            exit();
        }
        
        // JWT token验证
        $token = Request::header('Authorization');
        if ($token) {
            $this->userInfo = $this->verifyToken($token);
        }
    }
    
    // JWT token验证
    private function verifyToken($token)
    {
        try {
            $payload = JWT::decode($token, config('jwt.secret'), ['HS256']);
            return (array)$payload;
        } catch (Exception $e) {
            return [];
        }
    }
    
    // 统一响应格式
    protected function jsonSuccess($data = [], $msg = 'success')
    {
        return json([
            'code' => 200,
            'msg'  => $msg,
            'data' => $data
        ]);
    }
    
    protected function jsonError($msg = 'error', $code = 400)
    {
        return json([
            'code' => $code,
            'msg'  => $msg
        ]);
    }
}

八、部署与性能优化

Docker部署配置

# docker-compose.yml
version: '3.8'
services:
  nginx:
    image: nginx:1.21
    ports:
      - "80:80"
    volumes:
      - ./:/var/www/html
      - ./docker/nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - php
      
  php:
    image: php:8.0-fpm
    volumes:
      - ./:/var/www/html
    environment:
      - PHP_EXTENSION=pdo_mysql,redis,gd
      
  mysql:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=123456
      - MYSQL_DATABASE=rbac_system
    volumes:
      - mysql_data:/var/lib/mysql
      
  redis:
    image: redis:6.2
    ports:
      - "6379:6379"

volumes:
  mysql_data:

性能优化配置

// config/cache.php - Redis缓存配置
return [
    'default' => 'redis',
    'stores'  => [
        'redis' => [
            'type'       => 'redis',
            'host'       => '127.0.0.1',
            'port'       => 6379,
            'password'   => '',
            'select'     => 0,
            'timeout'    => 0,
            'persistent' => false,
            'prefix'     => 'rbac:',
        ],
    ],
];

// 路由缓存
php think optimize:route

// 配置缓存
php think optimize:config

// 自动加载缓存
php think optimize:schema

项目总结

实现的核心功能

  • 完整的RBAC权限管理系统
  • 多应用架构支持
  • 前后端分离API接口
  • 操作日志记录系统
  • Docker容器化部署

技术亮点

  • 基于ThinkPHP 6.x的现代化架构
  • 灵活的权限节点管理
  • 中间件化的权限验证
  • 高性能的缓存优化
  • 完善的错误处理机制

扩展建议

  • 集成工作流引擎
  • 实现数据权限控制
  • 添加消息推送功能
  • 集成第三方登录
  • 实现分布式部署

ThinkPHP 6.x企业级RBAC权限管理系统开发实战教程
收藏 (0) 打赏

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

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

淘吗网 thinkphp ThinkPHP 6.x企业级RBAC权限管理系统开发实战教程 https://www.taomawang.com/server/thinkphp/1112.html

常见问题

相关文章

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

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