前言:企业级权限管理的重要性
在现代企业应用开发中,权限管理是保障系统安全的核心环节。基于角色的访问控制(RBAC)模型通过角色和权限的灵活配置,为企业提供了一套完善的安全管理方案。本文将基于ThinkPHP 6.1框架,从零开始构建一个完整的企业级RBAC权限系统。
一、RBAC权限模型设计原理
1.1 核心概念解析
RBAC(Role-Based Access Control)模型包含四个核心元素:用户(User)、角色(Role)、权限(Permission)和操作(Operation)。通过用户-角色-权限的层级关系,实现灵活的权限控制。
1.2 数据库表结构设计
-- 用户表
CREATE TABLE `admin_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 '真实姓名',
`status` tinyint(1) DEFAULT '1' COMMENT '状态:1正常 0禁用',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 角色表
CREATE TABLE `admin_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 NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 权限表
CREATE TABLE `admin_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT '权限名称',
`path` varchar(255) NOT NULL COMMENT '权限路径',
`method` varchar(10) DEFAULT 'GET' COMMENT '请求方法',
`type` tinyint(1) DEFAULT '1' COMMENT '权限类型:1菜单 2按钮 3接口',
`parent_id` int(11) DEFAULT '0' COMMENT '父级权限ID',
`sort` int(11) DEFAULT '0' COMMENT '排序',
`icon` varchar(50) DEFAULT NULL COMMENT '图标',
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 用户角色关联表
CREATE TABLE `admin_user_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`role_id` int(11) NOT NULL,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `role_id` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 角色权限关联表
CREATE TABLE `admin_role_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role_id` int(11) NOT NULL,
`permission_id` int(11) NOT NULL,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `role_id` (`role_id`),
KEY `permission_id` (`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
二、ThinkPHP 6.1项目初始化与配置
2.1 项目创建与扩展安装
# 创建ThinkPHP项目
composer create-project topthink/think tp6-rbac
# 安装验证码扩展
composer require topthink/think-captcha
# 安装JWT扩展
composer require firebase/php-jwt
2.2 数据库配置
// config/database.php
return [
// 默认数据库连接
'default' => 'mysql',
// 数据库连接信息
'connections' => [
'mysql' => [
'type' => 'mysql',
'hostname' => '127.0.0.1',
'database' => 'tp6_rbac',
'username' => 'root',
'password' => '',
'hostport' => '3306',
'charset' => 'utf8mb4',
'prefix' => 'admin_',
'debug' => true,
]
]
];
2.3 模型层设计
// app/model/AdminUser.php
<?php
namespace appmodel;
use thinkModel;
use thinkmodelconcernSoftDelete;
class AdminUser extends Model
{
use SoftDelete;
protected $name = 'admin_user';
protected $autoWriteTimestamp = true;
protected $createTime = 'create_time';
protected $updateTime = 'update_time';
protected $deleteTime = 'delete_time';
protected $hidden = ['password', 'delete_time'];
// 用户角色关联
public function roles()
{
return $this->belongsToMany(AdminRole::class, 'admin_user_role', 'role_id', 'user_id');
}
// 密码加密
public function setPasswordAttr($value)
{
return password_hash($value, PASSWORD_DEFAULT);
}
// 验证密码
public function verifyPassword($password)
{
return password_verify($password, $this->password);
}
}
// app/model/AdminRole.php
<?php
namespace appmodel;
use thinkModel;
class AdminRole extends Model
{
protected $name = 'admin_role';
protected $autoWriteTimestamp = true;
protected $createTime = 'create_time';
// 角色权限关联
public function permissions()
{
return $this->belongsToMany(AdminPermission::class, 'admin_role_permission', 'permission_id', 'role_id');
}
// 角色用户关联
public function users()
{
return $this->belongsToMany(AdminUser::class, 'admin_user_role', 'user_id', 'role_id');
}
}
// app/model/AdminPermission.php
<?php
namespace appmodel;
use thinkModel;
class AdminPermission extends Model
{
protected $name = 'admin_permission';
protected $autoWriteTimestamp = true;
protected $createTime = 'create_time';
// 权限角色关联
public function roles()
{
return $this->belongsToMany(AdminRole::class, 'admin_role_permission', 'role_id', 'permission_id');
}
// 获取树形权限结构
public static function getTree($parentId = 0)
{
$permissions = self::where('parent_id', $parentId)
->order('sort', 'desc')
->select();
foreach ($permissions as $permission) {
$permission->children = self::getTree($permission->id);
}
return $permissions;
}
}
三、核心权限验证中间件开发
3.1 JWT令牌管理类
// app/common/JwtAuth.php
<?php
namespace appcommon;
use FirebaseJWTJWT;
use FirebaseJWTKey;
use thinkfacadeRequest;
class JwtAuth
{
private static $secretKey = 'your-secret-key-here';
private static $algorithm = 'HS256';
// 生成令牌
public static function generateToken($userId, $username)
{
$payload = [
'iss' => 'tp6-rbac', // 签发者
'iat' => time(), // 签发时间
'exp' => time() + 7200, // 过期时间2小时
'user_id' => $userId,
'username' => $username
];
return JWT::encode($payload, self::$secretKey, self::$algorithm);
}
// 验证令牌
public static function verifyToken($token)
{
try {
$decoded = JWT::decode($token, new Key(self::$secretKey, self::$algorithm));
return (array)$decoded;
} catch (Exception $e) {
return false;
}
}
// 从请求头获取令牌
public static function getTokenFromHeader()
{
$authorization = Request::header('authorization');
if ($authorization && preg_match('/Bearers+(.*)$/i', $authorization, $matches)) {
return $matches[1];
}
return null;
}
}
3.2 权限验证中间件
// app/middleware/AuthMiddleware.php
<?php
namespace appmiddleware;
use appcommonJwtAuth;
use appmodelAdminUser;
use thinkfacadeRequest;
class AuthMiddleware
{
public function handle($request, Closure $next)
{
// 获取令牌
$token = JwtAuth::getTokenFromHeader();
if (!$token) {
return json([
'code' => 401,
'message' => '未提供访问令牌',
'data' => null
]);
}
// 验证令牌
$payload = JwtAuth::verifyToken($token);
if (!$payload) {
return json([
'code' => 401,
'message' => '令牌无效或已过期',
'data' => null
]);
}
// 获取用户信息
$user = AdminUser::find($payload['user_id']);
if (!$user || $user->status != 1) {
return json([
'code' => 401,
'message' => '用户不存在或已被禁用',
'data' => null
]);
}
// 将用户信息存储到请求对象
$request->user = $user;
$request->user_id = $user->id;
return $next($request);
}
}
3.3 权限检查中间件
// app/middleware/PermissionMiddleware.php
<?php
namespace appmiddleware;
use thinkfacadeRequest;
class PermissionMiddleware
{
public function handle($request, Closure $next)
{
$user = $request->user;
$currentPath = Request::pathinfo();
$method = Request::method();
// 超级管理员拥有所有权限
if ($user->id == 1) {
return $next($request);
}
// 检查用户权限
$hasPermission = $this->checkUserPermission($user->id, $currentPath, $method);
if (!$hasPermission) {
return json([
'code' => 403,
'message' => '没有访问权限',
'data' => null
]);
}
return $next($request);
}
private function checkUserPermission($userId, $path, $method)
{
// 查询用户的所有权限
$permissions = AdminUser::with(['roles.permissions'])
->where('id', $userId)
->find()
->toArray();
$userPermissions = [];
foreach ($permissions['roles'] as $role) {
foreach ($role['permissions'] as $permission) {
$userPermissions[] = [
'path' => $permission['path'],
'method' => $permission['method']
];
}
}
// 检查当前请求是否在权限列表中
foreach ($userPermissions as $permission) {
if ($this->matchPermission($permission, $path, $method)) {
return true;
}
}
return false;
}
private function matchPermission($permission, $path, $method)
{
// 简单的路径匹配,实际项目中可以使用更复杂的路由匹配逻辑
$permissionPath = trim($permission['path'], '/');
$requestPath = trim($path, '/');
return $permissionPath === $requestPath &&
strtoupper($permission['method']) === strtoupper($method);
}
}
四、控制器与业务逻辑实现
4.1 用户认证控制器
// app/controller/Auth.php
<?php
namespace appcontroller;
use appBaseController;
use appcommonJwtAuth;
use appmodelAdminUser;
use thinkfacadeRequest;
use thinkfacadeValidate;
class Auth extends BaseController
{
// 用户登录
public function login()
{
$data = Request::only(['username', 'password', 'captcha']);
// 数据验证
$validate = Validate::rule([
'username|用户名' => 'require|length:3,20',
'password|密码' => 'require|length:6,20',
'captcha|验证码' => 'require|captcha'
]);
if (!$validate->check($data)) {
return json([
'code' => 400,
'message' => $validate->getError(),
'data' => null
]);
}
// 验证用户
$user = AdminUser::where('username', $data['username'])->find();
if (!$user || !$user->verifyPassword($data['password'])) {
return json([
'code' => 400,
'message' => '用户名或密码错误',
'data' => null
]);
}
if ($user->status != 1) {
return json([
'code' => 400,
'message' => '账户已被禁用',
'data' => null
]);
}
// 生成令牌
$token = JwtAuth::generateToken($user->id, $user->username);
// 更新最后登录时间
$user->save(['last_login_time' => date('Y-m-d H:i:s')]);
return json([
'code' => 200,
'message' => '登录成功',
'data' => [
'token' => $token,
'user_info' => [
'id' => $user->id,
'username' => $user->username,
'realname' => $user->realname
]
]
]);
}
// 获取当前用户信息
public function userInfo()
{
$user = Request::user;
// 获取用户权限菜单
$menus = $this->getUserMenus($user->id);
return json([
'code' => 200,
'message' => 'success',
'data' => [
'user_info' => $user->visible(['id', 'username', 'realname'])->toArray(),
'menus' => $menus
]
]);
}
// 获取用户菜单
private function getUserMenus($userId)
{
$user = AdminUser::with(['roles.permissions' => function($query) {
$query->where('type', 1)->order('sort', 'desc');
}])->where('id', $userId)->find();
$menus = [];
foreach ($user->roles as $role) {
foreach ($role->permissions as $permission) {
$menus[$permission->id] = $permission->toArray();
}
}
return $this->buildMenuTree(array_values($menus));
}
// 构建菜单树
private function buildMenuTree($menus, $parentId = 0)
{
$tree = [];
foreach ($menus as $menu) {
if ($menu['parent_id'] == $parentId) {
$children = $this->buildMenuTree($menus, $menu['id']);
if ($children) {
$menu['children'] = $children;
}
$tree[] = $menu;
}
}
return $tree;
}
}
4.2 用户管理控制器
// app/controller/User.php
<?php
namespace appcontroller;
use appBaseController;
use appmodelAdminUser;
use appmodelAdminRole;
use thinkfacadeRequest;
class User extends BaseController
{
// 用户列表
public function index()
{
$page = Request::param('page', 1);
$limit = Request::param('limit', 10);
$keyword = Request::param('keyword', '');
$query = AdminUser::with('roles');
if ($keyword) {
$query->whereLike('username|realname', "%{$keyword}%");
}
$list = $query->paginate([
'page' => $page,
'list_rows' => $limit
]);
return json([
'code' => 200,
'message' => 'success',
'data' => $list
]);
}
// 创建用户
public function create()
{
$data = Request::only(['username', 'password', 'realname', 'role_ids']);
// 验证用户名是否已存在
$exists = AdminUser::where('username', $data['username'])->find();
if ($exists) {
return json([
'code' => 400,
'message' => '用户名已存在',
'data' => null
]);
}
// 创建用户
$user = AdminUser::create($data);
// 分配角色
if (!empty($data['role_ids'])) {
$user->roles()->saveAll($data['role_ids']);
}
return json([
'code' => 200,
'message' => '用户创建成功',
'data' => null
]);
}
// 更新用户
public function update($id)
{
$data = Request::only(['realname', 'status', 'role_ids']);
$user = AdminUser::find($id);
if (!$user) {
return json([
'code' => 404,
'message' => '用户不存在',
'data' => null
]);
}
// 更新用户信息
$user->save($data);
// 更新角色
if (isset($data['role_ids'])) {
$user->roles()->detach();
if (!empty($data['role_ids'])) {
$user->roles()->saveAll($data['role_ids']);
}
}
return json([
'code' => 200,
'message' => '用户更新成功',
'data' => null
]);
}
}
五、路由配置与中间件应用
5.1 路由配置文件
// route/app.php
<?php
use thinkfacadeRoute;
// 认证相关路由
Route::group('auth', function() {
Route::post('login', 'Auth/login');
Route::get('userinfo', 'Auth/userInfo');
});
// 需要认证的路由组
Route::group(function() {
// 用户管理
Route::group('user', function() {
Route::get('/', 'User/index');
Route::post('/', 'User/create');
Route::put(':id', 'User/update');
Route::delete(':id', 'User/delete');
});
// 角色管理
Route::group('role', function() {
Route::get('/', 'Role/index');
Route::post('/', 'Role/create');
Route::put(':id', 'Role/update');
Route::get('permissions/:id', 'Role/getPermissions');
Route::post('permissions/:id', 'Role/setPermissions');
});
// 权限管理
Route::group('permission', function() {
Route::get('/', 'Permission/index');
Route::get('tree', 'Permission/tree');
Route::post('/', 'Permission/create');
Route::put(':id', 'Permission/update');
});
})->middleware([appmiddlewareAuthMiddleware::class, appmiddlewarePermissionMiddleware::class]);
六、系统测试与安全优化
6.1 功能测试用例
// 登录测试
POST /auth/login
{
"username": "admin",
"password": "123456",
"captcha": "abcd"
}
// 获取用户信息测试
GET /auth/userinfo
Headers: Authorization: Bearer {token}
// 用户列表测试
GET /user?page=1&limit=10
Headers: Authorization: Bearer {token}
6.2 安全优化措施
- 密码安全:使用password_hash进行强加密
- 令牌管理:JWT令牌设置合理过期时间
- SQL注入防护:使用ThinkPHP的ORM防止SQL注入
- XSS防护:输出数据进行HTML转义
- CSRF防护:启用ThinkPHP的CSRF保护中间件
- 请求限流:对API接口进行访问频率限制
6.3 性能优化建议
- 使用Redis缓存用户权限数据
- 对频繁查询的权限数据进行缓存
- 使用数据库连接池提高并发性能
- 对权限检查结果进行缓存,避免重复查询
七、部署与扩展方案
7.1 生产环境部署
# 关闭调试模式
// .env
APP_DEBUG = false
# 配置缓存
php think optimize:route
php think optimize:config
# 设置目录权限
chmod -R 755 runtime
chmod -R 755 public/uploads
7.2 系统扩展方案
基于当前RBAC系统,可以进一步扩展以下功能:
- 操作日志:记录用户操作行为
- 数据权限:基于组织架构的数据访问控制
- 多租户:支持多租户的SaaS系统
- API网关:集成API网关进行统一权限管理
- 单点登录:实现多系统间的单点登录
结语
本文详细介绍了基于ThinkPHP 6.1构建企业级RBAC权限管理系统的完整流程,从数据库设计、模型构建、中间件开发到控制器实现,涵盖了权限系统的所有核心环节。通过本系统的实现,不仅能够满足企业基本的权限管理需求,还提供了良好的扩展性和安全性。
在实际项目开发中,建议根据具体业务需求对系统进行定制化调整,同时结合缓存、日志、监控等辅助系统,构建更加完善的企业级应用架构。

