一、项目架构设计与环境准备
在ThinkPHP 6.0的多应用模式下,我们可以将后台管理系统和前端API分离为独立的应用模块。这种架构设计不仅提高了代码的可维护性,还能更好地适应现代Web开发的模块化需求。
1.1 创建多应用项目结构
// 安装ThinkPHP 6.0 composer create-project topthink/think tp6-auth-system // 安装多应用扩展 composer require topthink/think-multi-app // 创建应用目录 php think build admin php think build api
项目目录结构如下:
app ├── admin // 后台管理应用 │ ├── controller │ ├── model │ └── view ├── api // 前端接口应用 │ ├── controller │ └── model └── common // 公共模块 ├── model └── service
二、数据库设计与模型创建
2.1 RBAC权限表结构
我们采用经典的RBAC(基于角色的访问控制)模型,设计以下数据表:
-- 用户表 CREATE TABLE `auth_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(255) NOT NULL, `realname` varchar(50) DEFAULT NULL, `status` tinyint(1) DEFAULT '1', `create_time` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ); -- 角色表 CREATE TABLE `auth_role` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `description` varchar(255) DEFAULT NULL, `status` tinyint(1) DEFAULT '1', PRIMARY KEY (`id`) ); -- 权限节点表 CREATE TABLE `auth_rule` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `title` varchar(50) NOT NULL, `type` tinyint(1) DEFAULT '1', `status` tinyint(1) DEFAULT '1', `condition` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ); -- 用户角色关联表 CREATE TABLE `auth_user_role` ( `user_id` int(11) NOT NULL, `role_id` int(11) NOT NULL, PRIMARY KEY (`user_id`,`role_id`) ); -- 角色权限关联表 CREATE TABLE `auth_role_rule` ( `role_id` int(11) NOT NULL, `rule_id` int(11) NOT NULL, PRIMARY KEY (`role_id`,`rule_id`) );
2.2 创建模型类
在common模块中创建基础模型:
// app/common/model/User.php <?php namespace appcommonmodel; use thinkModel; class User extends Model { protected $name = 'auth_user'; // 密码自动加密 public function setPasswordAttr($value) { return password_hash($value, PASSWORD_DEFAULT); } // 关联角色 public function roles() { return $this->belongsToMany('Role', 'auth_user_role', 'role_id', 'user_id'); } } // app/common/model/Role.php <?php namespace appcommonmodel; use thinkModel; class Role extends Model { protected $name = 'auth_role'; // 关联权限 public function rules() { return $this->belongsToMany('Rule', 'auth_role_rule', 'rule_id', 'role_id'); } // 关联用户 public function users() { return $this->belongsToMany('User', 'auth_user_role', 'user_id', 'role_id'); } }
三、权限验证服务层设计
3.1 创建权限验证服务
// app/common/service/AuthService.php <?php namespace appcommonservice; use thinkfacadeSession; use appcommonmodelUser; use appcommonmodelRole; use appcommonmodelRule; class AuthService { protected static $instance; public static function instance() { if (is_null(self::$instance)) { self::$instance = new self(); } return self::$instance; } /** * 用户登录验证 */ public function login($username, $password) { $user = User::where('username', $username)->find(); if (!$user || $user->status != 1) { throw new Exception('用户不存在或已被禁用'); } if (!password_verify($password, $user->password)) { throw new Exception('密码错误'); } // 记录登录信息 Session::set('admin_id', $user->id); Session::set('admin_user', $user->toArray()); return $user; } /** * 检查用户权限 */ public function check($ruleName, $userId = null) { if (is_null($userId)) { $userId = Session::get('admin_id'); } if (!$userId) { return false; } // 超级管理员拥有所有权限 if ($this->isSuperAdmin($userId)) { return true; } $userRules = $this->getUserRules($userId); return in_array($ruleName, $userRules); } /** * 获取用户所有权限 */ protected function getUserRules($userId) { $cacheKey = 'user_rules_' . $userId; $rules = cache($cacheKey); if (!$rules) { $user = User::with(['roles.rules'])->find($userId); $rules = []; foreach ($user->roles as $role) { if ($role->status == 1) { foreach ($role->rules as $rule) { if ($rule->status == 1) { $rules[] = $rule->name; } } } } $rules = array_unique($rules); cache($cacheKey, $rules, 3600); } return $rules; } /** * 判断是否为超级管理员 */ protected function isSuperAdmin($userId) { // 这里可以根据实际情况定义超级管理员 $superAdmins = [1]; // 假设ID为1的用户是超级管理员 return in_array($userId, $superAdmins); } }
四、后台控制器实现
4.1 基础控制器与中间件
// app/admin/controller/Base.php <?php namespace appadmincontroller; use thinkController; use appcommonserviceAuthService; class Base extends Controller { protected $middleware = ['appadminmiddlewareAuth']; // 空操作 public function _empty() { return $this->error('页面不存在'); } } // app/admin/middleware/Auth.php <?php namespace appadminmiddleware; use thinkfacadeSession; use appcommonserviceAuthService; class Auth { public function handle($request, Closure $next) { // 排除登录页面 $controller = $request->controller(); $action = $request->action(); if ($controller == 'Login' && in_array($action, ['index', 'doLogin'])) { return $next($request); } // 检查登录状态 $adminId = Session::get('admin_id'); if (!$adminId) { return redirect('/admin/login/index'); } // 权限验证 $ruleName = strtolower($controller . '/' . $action); if (!AuthService::instance()->check($ruleName)) { if ($request->isAjax()) { return json(['code' => 403, 'msg' => '没有访问权限']); } else { return view('common@/error', ['msg' => '没有访问权限']); } } return $next($request); } }
4.2 用户管理控制器
// app/admin/controller/User.php <?php namespace appadmincontroller; use thinkfacadeRequest; use appcommonmodelUser as UserModel; use appcommonmodelRole; class User extends Base { /** * 用户列表 */ public function index() { $page = Request::param('page', 1); $limit = Request::param('limit', 15); $list = UserModel::with('roles') ->paginate([ 'list_rows' => $limit, 'page' => $page ]); return json([ 'code' => 0, 'data' => $list->items(), 'count' => $list->total() ]); } /** * 添加用户 */ public function add() { if (Request::isPost()) { $data = Request::post(); try { $user = UserModel::create($data); // 分配角色 if (!empty($data['role_ids'])) { $user->roles()->saveAll($data['role_ids']); } return json(['code' => 0, 'msg' => '添加成功']); } catch (Exception $e) { return json(['code' => 1, 'msg' => $e->getMessage()]); } } // 获取所有角色 $roles = Role::where('status', 1)->select(); return view('add', ['roles' => $roles]); } /** * 编辑用户 */ public function edit($id) { $user = UserModel::with('roles')->find($id); if (Request::isPost()) { $data = Request::post(); try { // 更新用户信息 if (!empty($data['password'])) { $user->password = $data['password']; } $user->realname = $data['realname']; $user->status = $data['status']; $user->save(); // 更新角色 $user->roles()->detach(); if (!empty($data['role_ids'])) { $user->roles()->saveAll($data['role_ids']); } return json(['code' => 0, 'msg' => '更新成功']); } catch (Exception $e) { return json(['code' => 1, 'msg' => $e->getMessage()]); } } $roles = Role::where('status', 1)->select(); return view('edit', [ 'user' => $user, 'roles' => $roles ]); } }
五、前端视图与API接口
5.1 使用Layui构建管理界面
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>用户管理</title> <link rel="stylesheet" href="/static/layui/css/layui.css" rel="external nofollow" > </head> <body> <div class="layui-card"> <div class="layui-card-header"> <div class="layui-row"> <div class="layui-col-md6"> <h2>用户管理</h2> </div> <div class="layui-col-md6 text-right"> <button class="layui-btn layui-btn-normal" onclick="addUser()"> <i class="layui-icon"></i>添加用户 </button> </div> </div> </div> <div class="layui-card-body"> <table id="userTable" lay-filter="userTable"></table> </div> </div> <script src="/static/layui/layui.js"></script> <script> layui.use(['table', 'form'], function(){ var table = layui.table; table.render({ elem: '#userTable', url: '/admin/user/index', page: true, cols: [[ {field: 'id', title: 'ID', width: 80}, {field: 'username', title: '用户名'}, {field: 'realname', title: '真实姓名'}, {field: 'status', title: '状态', templet: '#statusTpl'}, {field: 'create_time', title: '创建时间', templet: '#timeTpl'}, {title: '操作', toolbar: '#actionTpl', width: 200} ]] }); }); function addUser() { layer.open({ type: 2, title: '添加用户', shadeClose: true, shade: 0.8, area: ['800px', '600px'], content: '/admin/user/add' }); } </script> <!-- 模板脚本 --> <script type="text/html" id="statusTpl"> {{# if(d.status == 1){ }} <span class="layui-badge layui-bg-green">正常</span> {{# } else { }} <span class="layui-badge layui-bg-gray">禁用</span> {{# } }} </script> <script type="text/html" id="actionTpl"> <a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a> <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a> </script> </body> </html>
5.2 API接口控制器
// app/api/controller/Base.php <?php namespace appapicontroller; use thinkController; use thinkfacadeRequest; class Base extends Controller { protected $middleware = ['appapimiddlewareAuth']; // 统一响应格式 protected function success($data = [], $msg = 'success') { return json([ 'code' => 0, 'msg' => $msg, 'data' => $data ]); } protected function error($msg = 'error', $code = 1) { return json([ 'code' => $code, 'msg' => $msg ]); } } // app/api/controller/User.php <?php namespace appapicontroller; use appcommonmodelUser as UserModel; class User extends Base { /** * 获取用户信息 */ public function info() { $userId = Request::middleware('user_id'); $user = UserModel::with('roles.rules') ->field('id,username,realname,create_time') ->find($userId); return $this->success($user); } /** * 更新用户信息 */ public function update() { $userId = Request::middleware('user_id'); $data = Request::post(); $user = UserModel::find($userId); if (!$user) { return $this->error('用户不存在'); } try { $user->allowField(['realname'])->save($data); return $this->success([], '更新成功'); } catch (Exception $e) { return $this->error($e->getMessage()); } } }
六、系统优化与安全考虑
6.1 性能优化策略
- 缓存策略:用户权限信息使用Redis缓存,减少数据库查询
- 数据库索引:为频繁查询的字段建立合适的索引
- 懒加载优化:合理使用模型关联的with预加载
6.2 安全防护措施
- 密码安全:使用password_hash进行密码加密
- SQL注入防护:使用ThinkPHP的ORM防止SQL注入
- XSS防护:对用户输入进行过滤和转义
- CSRF防护:启用ThinkPHP的CSRF防护中间件
6.3 扩展性设计
- 模块化设计:服务层、模型层、控制器层分离
- 多应用支持:支持后台管理和API接口分离
- 插件机制:预留插件扩展接口