本文目录导读:

我来为您设计一个完整的ThinkPHP用户权限RBAC系统。
数据库设计
数据表结构
-- 用户表 CREATE TABLE `tp_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL COMMENT '用户名', `password` varchar(255) NOT NULL COMMENT '密码', `real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名', `email` varchar(100) DEFAULT NULL COMMENT '邮箱', `phone` varchar(20) DEFAULT NULL COMMENT '手机号', `status` tinyint(1) DEFAULT '1' COMMENT '状态:1启用 0禁用', `last_login_time` datetime DEFAULT NULL COMMENT '最后登录时间', `last_login_ip` varchar(50) DEFAULT NULL COMMENT '最后登录IP', `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; -- 角色表 CREATE TABLE `tp_role` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL COMMENT '角色名称', `code` varchar(50) NOT NULL COMMENT '角色标识', `description` varchar(255) 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 `code` (`code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表'; -- 权限表(菜单/节点) CREATE TABLE `tp_permission` ( `id` int(11) NOT NULL AUTO_INCREMENT, `parent_id` int(11) DEFAULT '0' COMMENT '父权限ID', `name` varchar(50) NOT NULL COMMENT '权限名称', `type` tinyint(1) DEFAULT '1' COMMENT '类型:1菜单 2按钮 3API', `url` varchar(255) DEFAULT NULL COMMENT '路由地址', `icon` varchar(50) DEFAULT NULL COMMENT '图标', `sort` int(11) DEFAULT '0' COMMENT '排序', `status` tinyint(1) DEFAULT '1' COMMENT '状态:1启用 0禁用', `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='权限表'; -- 用户角色关联表 CREATE TABLE `tp_user_role` ( `user_id` int(11) NOT NULL, `role_id` int(11) NOT NULL, PRIMARY KEY (`user_id`,`role_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户角色关联表'; -- 角色权限关联表 CREATE TABLE `tp_role_permission` ( `role_id` int(11) NOT NULL, `permission_id` int(11) NOT NULL, PRIMARY KEY (`role_id`,`permission_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色权限关联表';
模型创建
用户模型
<?php
// app/model/User.php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
class User extends Model
{
use SoftDelete;
protected $deleteTime = 'delete_time';
// 关联角色
public function roles()
{
return $this->belongsToMany(Role::class, 'user_role', 'role_id', 'user_id');
}
// 密码加密
public function setPasswordAttr($value)
{
return password_hash($value, PASSWORD_BCRYPT);
}
// 验证密码
public function verifyPassword($password)
{
return password_verify($password, $this->password);
}
// 获取用户所有权限
public function getPermissions()
{
$permissionIds = [];
$roles = $this->roles()->where('status', 1)->select();
foreach ($roles as $role) {
$permissions = $role->permissions()->where('status', 1)->select();
foreach ($permissions as $permission) {
$permissionIds[$permission->url] = true;
}
}
return array_keys($permissionIds);
}
// 检查权限
public function hasPermission($permissionUrl)
{
$permissions = $this->getPermissions();
return in_array($permissionUrl, $permissions);
}
// 检查角色
public function hasRole($roleCode)
{
$roles = $this->roles()->where('code', $roleCode)->find();
return $roles ? true : false;
}
}
角色模型
<?php
// app/model/Role.php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
class Role extends Model
{
use SoftDelete;
// 关联用户
public function users()
{
return $this->belongsToMany(User::class, 'user_role', 'user_id', 'role_id');
}
// 关联权限
public function permissions()
{
return $this->belongsToMany(Permission::class, 'role_permission', 'permission_id', 'role_id');
}
// 添加角色并绑定用户
public static function createRole($data, $userIds = [])
{
$role = self::create($data);
if (!empty($userIds)) {
$role->users()->attach($userIds);
}
return $role;
}
}
权限模型
<?php
// app/model/Permission.php
namespace app\model;
use think\Model;
class Permission extends Model
{
// 关联角色
public function roles()
{
return $this->belongsToMany(Role::class, 'role_permission', 'role_id', 'permission_id');
}
// 获取树形权限
public static function getTree($parentId = 0)
{
$permissions = self::where('parent_id', $parentId)
->order('sort', 'asc')
->select()
->toArray();
foreach ($permissions as &$permission) {
$children = self::getTree($permission['id']);
if (!empty($children)) {
$permission['children'] = $children;
}
}
return $permissions;
}
}
中间件实现
<?php
// app/middleware/AuthCheck.php
namespace app\middleware;
use think\facade\Session;
use think\facade\Url;
class AuthCheck
{
public function handle($request, \Closure $next)
{
// 检查是否登录
if (!Session::has('user_id')) {
if ($request->isAjax()) {
return json(['code' => 401, 'msg' => '请先登录']);
}
return redirect((string)Url::build('login/index'));
}
// 获取当前请求的模块、控制器、方法
$module = app('http')->getName();
$controller = $request->controller();
$action = $request->action();
// 构建权限标识
$permission = "{$module}/{$controller}/{$action}";
// 超级管理员跳过验证
$user = \app\model\User::find(Session::get('user_id'));
if ($user->hasRole('admin')) {
return $next($request);
}
// 检查权限
if (!$user->hasPermission($permission)) {
if ($request->isAjax()) {
return json(['code' => 403, 'msg' => '没有权限']);
}
abort(403, '没有访问权限');
}
return $next($request);
}
}
认证服务类
<?php
// app/service/AuthService.php
namespace app\service;
use app\model\User;
use app\model\Role;
use app\model\Permission;
use think\facade\Session;
use think\facade\Cache;
class AuthService
{
/**
* 登录认证
*/
public function login($username, $password)
{
$user = User::where('username', $username)
->where('status', 1)
->find();
if (!$user) {
return ['code' => 0, 'msg' => '用户不存在或已被禁用'];
}
if (!$user->verifyPassword($password)) {
return ['code' => 0, 'msg' => '密码错误'];
}
// 更新登录信息
$user->last_login_time = date('Y-m-d H:i:s');
$user->last_login_ip = request()->ip();
$user->save();
// 设置Session
Session::set('user_id', $user->id);
Session::set('user_info', $user->toArray());
// 缓存权限
$this->cacheUserPermissions($user->id);
return ['code' => 1, 'msg' => '登录成功', 'user' => $user];
}
/**
* 缓存用户权限
*/
public function cacheUserPermissions($userId)
{
$user = User::find($userId);
$permissions = $user->getPermissions();
Cache::set("user_permissions_{$userId}", $permissions, 120);
return $permissions;
}
/**
* 退出登录
*/
public function logout()
{
$userId = Session::get('user_id');
Cache::delete("user_permissions_{$userId}");
Session::clear();
}
/**
* 获取当前用户信息
*/
public function getUserInfo()
{
$userId = Session::get('user_id');
if (!$userId) {
return null;
}
$user = User::with(['roles'])
->find($userId);
return $user;
}
/**
* 生成权限树
*/
public function getPermissionTree()
{
$user = $this->getUserInfo();
if (!$user) {
return [];
}
// 超级管理员获取所有权限
if ($user->hasRole('admin')) {
$permissions = Permission::where('type', 1)
->order('sort', 'asc')
->select()
->toArray();
} else {
// 普通用户获取自己的权限菜单
$roleIds = $user->roles()->column('id');
$permissionIds = \think\facade\Db::name('role_permission')
->whereIn('role_id', $roleIds)
->column('permission_id');
$permissions = Permission::whereIn('id', $permissionIds)
->where('type', 1)
->where('status', 1)
->order('sort', 'asc')
->select()
->toArray();
}
return $this->buildTree($permissions);
}
/**
* 构建树形结构
*/
private function buildTree($data, $parentId = 0)
{
$tree = [];
foreach ($data as $item) {
if ($item['parent_id'] == $parentId) {
$children = $this->buildTree($data, $item['id']);
if ($children) {
$item['children'] = $children;
}
$tree[] = $item;
}
}
return $tree;
}
}
控制器示例
<?php
// app/controller/Login.php
namespace app\controller;
use think\Request;
use app\service\AuthService;
class Login
{
protected $authService;
public function __construct(AuthService $authService)
{
$this->authService = $authService;
}
// 显示登录页面
public function index()
{
return view('login/index');
}
// 处理登录
public function login(Request $request)
{
$username = $request->post('username');
$password = $request->post('password');
$result = $this->authService->login($username, $password);
if ($result['code'] == 1) {
return json(['code' => 1, 'msg' => '登录成功', 'url' => '/index']);
}
return json(['code' => 0, 'msg' => $result['msg']]);
}
// 退出登录
public function logout()
{
$this->authService->logout();
return redirect('/login');
}
}
<?php
// app/controller/User.php
namespace app\controller;
use app\model\User;
use app\model\Role;
use think\Request;
class User extends Base
{
// 用户列表
public function index()
{
$users = User::with('roles')->paginate(10);
return view('user/index', ['users' => $users]);
}
// 添加用户
public function add()
{
if (request()->isPost()) {
$data = request()->post();
$roles = $data['roles'] ?? [];
unset($data['roles']);
$user = User::create($data);
if (!empty($roles)) {
$user->roles()->attach($roles);
}
return json(['code' => 1, 'msg' => '添加成功']);
}
$roles = Role::where('status', 1)->select();
return view('user/add', ['roles' => $roles]);
}
// 分配角色
public function assignRole($userId)
{
if (request()->isPost()) {
$roleIds = request()->post('roles', []);
$user = User::find($userId);
$user->roles()->detach();
if (!empty($roleIds)) {
$user->roles()->attach($roleIds);
}
// 清除权限缓存
\think\facade\Cache::delete("user_permissions_{$userId}");
return json(['code' => 1, 'msg' => '分配成功']);
}
$user = User::with('roles')->find($userId);
$roles = Role::where('status', 1)->select();
return view('user/assign_role', [
'user' => $user,
'roles' => $roles
]);
}
}
路由配置
<?php
// route/app.php
use think\facade\Route;
// 登录相关
Route::get('login', 'Login/index');
Route::post('login', 'Login/login');
Route::get('logout', 'Login/logout');
// 需要认证的路由
Route::group(function () {
// 首页
Route::get('/', 'Index/index');
Route::get('index', 'Index/index');
// 用户管理
Route::group('user', function () {
Route::get('/', 'User/index');
Route::get('add', 'User/add');
Route::post('add', 'User/add');
Route::get('edit/:id', 'User/edit');
Route::post('edit', 'User/edit');
Route::post('delete/:id', 'User/delete');
Route::get('assign/:id', 'User/assignRole');
Route::post('assign', 'User/assignRole');
});
// 角色管理
Route::group('role', function () {
Route::get('/', 'Role/index');
Route::get('add', 'Role/add');
Route::post('add', 'Role/add');
Route::post('delete/:id', 'Role/delete');
});
})->middleware(\app\middleware\AuthCheck::class);
视图模板示例
<!-- app/view/layout/main.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">{$title|default='管理系统'}</title>
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<div class="layout">
<div class="sidebar">
<ul>
{foreach $menus as $menu}
{if isset($menu['children'])}
<li class="has-sub">
<a href="javascript:;">{$menu.name}</a>
<ul>
{foreach $menu['children'] as $child}
<li><a href="{$child.url}">{$child.name}</a></li>
{/foreach}
</ul>
</li>
{else}
<li><a href="{$menu.url}">{$menu.name}</a></li>
{/if}
{/foreach}
</ul>
</div>
<div class="main">
{__CONTENT__}
</div>
</div>
</body>
</html>
初始化数据
<?php
// database/seed/RbacSeeder.php
namespace database\seed;
use think\Db;
class RbacSeeder
{
public function run()
{
// 创建超级管理员角色
$adminRoleId = Db::name('role')->insertGetId([
'name' => '超级管理员',
'code' => 'admin',
'description' => '拥有所有权限',
'status' => 1,
'create_time' => date('Y-m-d H:i:s')
]);
// 创建默认用户
$userId = Db::name('user')->insertGetId([
'username' => 'admin',
'password' => password_hash('123456', PASSWORD_BCRYPT),
'real_name' => '管理员',
'status' => 1,
'create_time' => date('Y-m-d H:i:s')
]);
// 绑定用户角色
Db::name('user_role')->insert([
'user_id' => $userId,
'role_id' => $adminRoleId
]);
// 创建权限数据
$permissions = [
['name' => '系统管理', 'parent_id' => 0, 'url' => '/system', 'sort' => 1],
['name' => '用户管理', 'parent_id' => 1, 'url' => '/user', 'sort' => 1],
['name' => '角色管理', 'parent_id' => 1, 'url' => '/role', 'sort' => 2],
['name' => '权限管理', 'parent_id' => 1, 'url' => '/permission', 'sort' => 3],
];
foreach ($permissions as $permission) {
$permissionId = Db::name('permission')->insertGetId($permission);
// 为超级管理员分配所有权限
Db::name('role_permission')->insert([
'role_id' => $adminRoleId,
'permission_id' => $permissionId
]);
}
}
}
扩展功能建议
- 多级权限控制: 支持菜单、按钮、API级别的权限控制
- 权限缓存: 使用Redis缓存用户权限,提高性能
- 操作日志: 记录用户关键操作日志
- 数据权限: 扩展实现数据级别的权限控制
- 登录限流: 防止暴力破解
- 单点登录: 同一账号仅允许一处登录
- 权限动态更新: 管理员修改权限后自动刷新所有用户缓存
安全建议
- 密码必须加密存储
- Token认证 + Session双机制
- CSRF防护
- SQL注入防护
- XSS攻击防护
- 访问频率限制
- 日志审计系统
这个RBAC系统设计完整,可以满足大部分中小型项目的权限管理需求,可以根据实际需求调整功能,比如增加数据权限、组织架构等。