一、项目架构设计与环境准备
在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接口分离
- 插件机制:预留插件扩展接口

