🔐 权限管理
ThinkAdmin v6 的权限管理基于简化的 RBAC 模型,并加入了注解权限配置。权限控制能够精确到按钮级别,为使用者提供了更大的灵活性。
📚 基础概念
🤔 基本介绍
权限管理是控制用户能够访问哪些功能和资源的机制。
简单理解:就像门禁系统,只有有权限的人才能进入特定的房间。
实际例子:
普通用户 → 只能查看自己的信息
管理员 → 可以查看所有用户信息
超级管理员 → 可以删除用户在 ThinkAdmin 中,权限管理确保只有授权用户才能访问特定的功能,保护系统安全。
🤔 RBAC 模型
RBAC(Role-Based Access Control,基于角色的访问控制)是一种权限管理模型。
简单理解:给用户分配角色,角色拥有权限,用户通过角色获得权限。
传统方式(不推荐):
用户A → 直接分配权限:查看用户、编辑用户、删除用户
用户B → 直接分配权限:查看用户RBAC 方式(推荐):
角色:管理员 → 拥有权限:查看用户、编辑用户、删除用户
角色:编辑 → 拥有权限:查看用户、编辑用户
用户A → 分配角色:管理员
用户B → 分配角色:编辑RBAC 的优势:
- 简化管理:只需管理角色权限,不需要为每个用户单独配置
- 易于维护:修改角色权限,所有该角色的用户自动生效
- 灵活扩展:可以创建多个角色,满足不同需求
🏗️ ThinkAdmin 权限模型
ThinkAdmin 使用简化的 RBAC 模型,包含四个核心概念:
1. 功能节点(Node)
系统根据控制器方法自动生成,格式为:应用/控制器/方法
// 控制器:app\admin\controller\User
// 方法:index()
// 生成的节点:admin/user/index实际例子:
admin/user/index- 用户列表页面admin/user/add- 添加用户页面admin/user/edit- 编辑用户页面admin/user/remove- 删除用户操作
2. 权限(Auth)
权限组,包含多个功能节点。
// 权限:用户管理
// 包含节点:
// - admin/user/index(查看用户列表)
// - admin/user/add(添加用户)
// - admin/user/edit(编辑用户)
// - admin/user/remove(删除用户)3. 用户(User)
系统使用者,被分配一个或多个权限。
// 用户:张三
// 分配权限:用户管理、商品管理
// 可以访问:用户管理、商品管理的所有功能节点4. 菜单(Menu)
根据权限控制菜单显示,只有拥有权限的用户才能看到对应的菜单。
// 菜单:用户管理
// 关联节点:admin/user/index
// 只有拥有 admin/user/index 权限的用户才能看到这个菜单📝 注解说明
注解是在代码注释中使用的特殊标记,用于配置权限和菜单。
简单理解:在方法注释中添加特殊标记,告诉系统这个方法的权限要求。
基础示例:
/**
* 用户列表
* @auth true # 需要权限验证
* @menu true # 添加到菜单
*/
public function index() { }注解说明:
| 注解 | 说明 | 效果 |
|---|---|---|
@auth true | 需要权限验证 | 访问需要配置授权才能访问 |
@menu true | 添加到菜单 | 在编辑菜单时自动提示节点可选项 |
@login true | 强制登录 | 强制需要登录才能访问该操作 |
完整示例:
/**
* 用户列表页面
* @auth true # 表示需要验证权限
* @menu true # 添加系统菜单节点
* @login true # 强制登录才可访问
*/
public function index(){
// 用户列表逻辑
}
/**
* 添加用户
* @auth true
* @menu true
*/
public function add(){
// 添加用户逻辑
}
/**
* 删除用户
* @auth true
*/
public function remove(){
// 删除用户逻辑(不需要显示在菜单中)
}⚙️ 权限验证流程
权限验证是自动的,系统会根据注解和配置自动检查权限。
步骤1:用户访问页面
用户在浏览器访问:http://example.com/admin/user/index步骤2:系统检查注解
// 系统检查方法注释
/**
* @auth true // 发现需要权限验证
*/
public function index() { }步骤3:检查用户权限
// 系统检查用户是否拥有该权限节点
$node = 'admin/user/index';
$hasAuth = auth($node); // 检查用户是否有权限
if (!$hasAuth) {
// 没有权限,拒绝访问
$this->error('权限不足!');
}步骤4:允许或拒绝访问
有权限 → 允许访问,显示页面
无权限 → 拒绝访问,显示错误提示完整流程:
用户访问 → 检查注解 → 检查权限 → 允许/拒绝
↓
@auth true
↓
admin/user/index
↓
用户是否有权限?
↓
是 → 允许访问
否 → 拒绝访问🚀 权限管理特点
核心特性
- 简化流程: 整合了功能节点、权限管理、菜单管理和用户管理
- 自动维护: 功能节点由系统自动维护,根据控制器代码注释进行刷新
- 注解配置: 只需添加标准的块注释即可加入权限控制
- 精确控制: 权限控制精确到按钮级别
技术优势
- 基于RBAC: 基于角色访问控制模型
- 注解驱动: 通过注解自动生成权限节点
- 细粒度控制: 支持到按钮级别的权限控制
- 动态管理: 支持动态权限配置和管理
🔄 管理流程
- 功能节点: 系统根据控制器注释自动生成
- 权限配置: 在后台配置权限与功能节点的关联
- 用户授权: 为用户分配相应的权限
- 菜单管理: 根据权限控制菜单显示
📝 注解规则
基础注解说明
注解规则案例如下,@auth 优先级高于 @login 配置,通常只需要配置 @auth 即可添加到后台权限配置。
/**
* 用户列表页面
* @auth true # 表示需要验证权限
* @menu true # 添加系统菜单节点
* @login true # 强制登录才可访问
*/
public function index(){
// 用户列表逻辑
}
/**
* 添加用户
* @auth true
* @menu true
*/
public function add(){
// 添加用户逻辑
}
/**
* 删除用户
* @auth true
*/
public function remove(){
// 删除用户逻辑
}注解参数详解
| 注解 | 说明 | 示例 | 效果 |
|---|---|---|---|
@auth true | 需要权限验证 | @auth true | 访问需要配置授权才能访问 |
@menu true | 添加到菜单 | @menu true | 在编辑菜单时自动提示节点可选项 |
@login true | 强制登录 | @login true | 强制需要登录才能访问该操作 |
实际应用案例
让我们看一个完整的用户管理模块权限配置:
<?php
declare(strict_types=1);
namespace app\admin\controller;
use think\admin\Controller;
use think\admin\model\SystemUser;
/**
* 系统用户管理
* @class User
* @package app\admin\controller
*/
class User extends Controller
{
/**
* 系统用户管理
* @auth true
* @menu true
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function index()
{
SystemUser::mQuery()->layTable(function () {
$this->title = '系统用户管理';
});
}
/**
* 添加系统用户
* @auth true
*/
public function add()
{
SystemUser::mForm('form');
}
/**
* 编辑系统用户
* @auth true
*/
public function edit()
{
SystemUser::mForm('form');
}
/**
* 删除系统用户 - 需要权限验证,但不显示在菜单中
* @auth true
*/
public function remove()
{
$this->_checkInput();
SystemUser::mDelete();
}
/**
* 检查输入变量(私有方法,防止删除系统超级账号)
*/
private function _checkInput()
{
if (in_array('10000', str2arr(input('id', '')))) {
$this->error('系统超级账号禁止删除!');
}
}
/**
* 用户详情 - 需要登录,不需要权限验证
* @login true
*/
public function detail()
{
// 用户详情逻辑
}
/**
* 公开页面 - 不需要任何验证
*/
public function public()
{
// 公开页面逻辑
}
}权限节点生成规则
系统会根据控制器和方法名自动生成权限节点:
- 控制器:
User→user(控制器类名,去掉 Controller 后缀) - 方法:
index→user/index - 完整节点:
admin/user/index
节点命名示例:
admin/user/index- 用户列表admin/user/add- 添加用户admin/user/edit- 编辑用户admin/user/remove- 删除用户admin/user/state- 修改用户状态
🔐 权限配置
创建权限后,需要为权限配置可访问的功能节点。例如,若权限A仅允许访问特定的功能节点,您需要在配置中勾选这些节点。
📝 配置应用名称
在配置授权时,若需展示应用名称,请前往 config/app.php 文件设置 app_names 的应用名称。
配置示例:
// config/app.php
return [
// 应用名称配置(用于权限管理界面显示)
'app_names' => [
'admin' => '系统管理',
'wechat' => '微信管理',
'plugin-account' => '账号管理'
],
];注意事项:
- 这些名称在显示前会经过
lang()函数进行语言转换处理 - 确保在不同语言环境下均能正确显示
- 如果应用名称未配置,将显示应用代码(如
admin)
🚫 忽略权限检查
若您不希望某个应用受到后台权限控制,可以通过配置 rbac_ignore 选项来实现。
配置示例:
// config/app.php
return [
// 忽略 RBAC 权限检查,可以配置多个应用
'rbac_ignore' => ['index', 'wap', 'api'],
];使用场景:
- 前台应用:
index应用通常不需要权限控制 - 移动端应用:
wap应用可能需要不同的权限机制 - API 应用:
api应用可能使用 Token 验证
注意事项:
- 被忽略的应用不会进行权限检查
- 所有用户都可以访问被忽略的应用
- 建议只忽略确实不需要权限控制的应用
🔑 登录地址配置
通常不需要配置,系统会自动处理登录地址。
// config/app.php
return [
// 配置 RBAC 登录地址,通常不需要配置
'rbac_login' => ''
];使用场景:
- 自定义登录页面地址
- 多应用共享登录页面
- 特殊登录流程
📋 权限配置步骤
步骤1:创建权限
系统管理 → 权限管理 → 添加权限步骤2:配置功能节点
选择权限 → 编辑 → 勾选功能节点步骤3:分配权限给用户
系统管理 → 用户管理 → 编辑用户 → 分配权限实际例子:
权限:用户管理
功能节点:
✓ admin/user/index(查看用户列表)
✓ admin/user/add(添加用户)
✓ admin/user/edit(编辑用户)
✗ admin/user/remove(删除用户,未勾选)
用户:张三
分配权限:用户管理
可以访问:查看、添加、编辑用户
不能访问:删除用户
📋 菜单管理
菜单支持层级结构,最大深度为三级,其中上级菜单占据一级,左侧菜单占据两级。
📝 菜单节点命名
在创建和编辑菜单时,务必仔细遵循菜单节点命名的规范。
命名格式:应用/控制器/方法
正确示例:
admin/user/index ✓ 正确
admin/user/add ✓ 正确
admin/menu/index ✓ 正确错误示例:
/admin/user/index ✗ 错误(前面不能有斜杠)
admin/user/index/ ✗ 错误(后面不能有斜杠)
user/index ✗ 错误(缺少应用名)🎯 自动提示功能
若在控制器方法的节点注释中标注了 @menu true,则该节点会自动出现在快捷提示列表中。
使用方法:
/**
* 用户列表
* @auth true
* @menu true # 添加此标记后,节点会自动出现在菜单管理的提示列表中
*/
public function index() { }实际效果:
菜单管理 → 编辑菜单 → 选择节点
↓
快捷提示列表:
- admin/user/index(用户列表)
- admin/user/add(添加用户)
- admin/user/edit(编辑用户)
...优势:
- 方便用户直接从列表中选取
- 无需手动输入,避免输入错误
- 提高操作效率
📊 菜单层级结构
菜单支持三级结构,合理组织菜单层级可以提升用户体验。
一级菜单(上级菜单):
系统管理
├── 用户管理
├── 权限管理
└── 菜单管理二级菜单(左侧菜单):
用户管理
├── 用户列表
├── 添加用户
└── 用户分组三级菜单(子菜单):
用户列表
├── 全部用户
├── 活跃用户
└── 禁用用户实际配置示例:
菜单名称:系统管理
节点:admin/index/index
类型:上级菜单
菜单名称:用户管理
节点:admin/user/index
类型:左侧菜单
上级菜单:系统管理
菜单名称:用户列表
节点:admin/user/index
类型:子菜单
上级菜单:用户管理
👤 用户管理
在后台创建新的用户账号后,您需要为该账号分配已配置好的权限,这样用户登录后便能显示对应的菜单及访问权限。
📝 创建用户
步骤1:创建用户账号
系统管理 → 用户管理 → 添加用户步骤2:填写用户信息
用户名:zhangsan
密码:123456
姓名:张三
邮箱:zhangsan@example.com步骤3:分配权限
选择权限:
✓ 用户管理
✓ 商品管理
✗ 订单管理(未勾选)👑 超级管理员
系统默认提供的 admin 账号是超级用户,它拥有访问系统所有节点的权限。
超级管理员特点:
- 拥有所有权限,无需配置
- 可以访问所有功能节点
- 可以管理所有用户和权限
检查是否为超级管理员:
use think\admin\service\AdminService;
// 检查当前用户是否为超级管理员
if (AdminService::isSuper()) {
// 超级管理员逻辑
}修改超级管理员账号名:
// config/app.php
return [
// 修改超级管理员账号名
'super_name' => 'admin', // 改为其他名称,如 'superadmin'
];注意事项:
- 超级管理员账号名修改后,需要使用新名称登录
- 建议不要频繁修改超级管理员账号名
- 确保至少有一个超级管理员账号
🔐 权限分配
为用户分配权限后,用户登录后便能显示对应的菜单及访问权限。
权限分配方式:
方式1:直接分配权限
用户:张三
分配权限:
- 用户管理
- 商品管理方式2:通过角色分配(如果使用角色)
用户:张三
分配角色:管理员
角色权限:
- 用户管理
- 商品管理
- 订单管理实际效果:
用户登录后:
✓ 可以看到"用户管理"菜单
✓ 可以看到"商品管理"菜单
✗ 看不到"订单管理"菜单(未分配权限)
✗ 无法访问订单管理功能(无权限)
🔐 权限管理深入应用
✅ 最佳实践
1. 控制器中的权限检查
<?php
declare(strict_types=1);
namespace app\admin\controller;
use think\admin\Controller;
use think\admin\service\AdminService;
use think\admin\model\SystemUser;
/**
* 系统用户管理
* @class User
* @package app\admin\controller
*/
class User extends Controller
{
/**
* 系统用户管理
* @auth true
* @menu true
*/
public function index()
{
// 权限注解已经处理了基础权限检查
// 可以在这里进行额外的权限逻辑
$this->title = '系统用户管理';
SystemUser::mQuery()->layTable();
}
/**
* 删除系统用户
* @auth true
*/
public function remove()
{
// 方法级别的权限检查
if (!AdminService::isSuper()) {
// 非超级管理员需要额外验证
$this->error('只有超级管理员可以删除用户!');
}
// 防止删除系统超级账号
if (in_array('10000', str2arr(input('id', '')))) {
$this->error('系统超级账号禁止删除!');
}
SystemUser::mDelete();
}
/**
* 修改用户资料(登录用户即可访问)
* @login true
*/
public function info()
{
// 只能修改自己的资料
$userId = AdminService::getUserId();
$id = input('id');
if ($id != $userId && !AdminService::isSuper()) {
$this->error('只能修改自己的资料!');
}
SystemUser::mForm('form');
}
}2. 前端权限控制
在模板中使用权限判断:
<!-- 使用权限判断显示/隐藏按钮 -->
<!--{if auth('admin/user/remove')}-->
<button data-action="{:url('remove')}" class="layui-btn layui-btn-danger">删除</button>
<!--{/if}-->
<!-- 使用权限判断显示/隐藏菜单项 -->
<!--{if auth('admin/user/index')}-->
<li><a href="{:url('admin/user/index')}">用户管理</a></li>
<!--{/if}-->3. 动态权限配置
// 在 config/app.php 中配置
return [
// 应用名称配置(用于权限管理界面显示)
'app_names' => [
'admin' => '系统管理',
'wechat' => '微信管理',
'plugin-account' => '账号管理',
],
// 忽略 RBAC 权限检查的应用(这些应用不需要权限验证)
'rbac_ignore' => ['index', 'wap', 'api'],
// RBAC 登录地址(通常不需要配置)
'rbac_login' => '',
];4. 权限节点自动生成
系统会根据控制器方法的注释自动生成权限节点:
/**
* 用户列表
* @auth true # 生成节点:admin/user/index
* @menu true # 在菜单管理中显示
*/
public function index() { }
/**
* 添加用户
* @auth true # 生成节点:admin/user/add
*/
public function add() { }
/**
* 删除用户
* @auth true # 生成节点:admin/user/remove
*/
public function remove() { }权限节点命名规则:
- 应用名:从控制器命名空间获取,如
app\admin\controller→admin - 控制器名:去掉
Controller后缀,如UserController→user - 方法名:直接使用,如
index→index - 完整节点:
admin/user/index
5. 超级管理员特殊处理
// 检查是否为超级管理员
if (AdminService::isSuper()) {
// 超级管理员拥有所有权限,无需额外检查
// 可以执行任何操作
}
// 获取超级管理员账号名
$superName = AdminService::getSuperName(); // 默认:admin
// 在配置文件中修改超级管理员账号名
// config/app.php
return [
'super_name' => 'admin', // 修改为其他名称
];6. 权限继承和组合
/**
* 批量操作(需要多个权限)
* @auth true
*/
public function batch()
{
// 检查是否拥有批量操作所需的所有权限
$requiredNodes = [
'admin/user/edit',
'admin/user/state',
];
foreach ($requiredNodes as $node) {
if (!auth($node)) {
$this->error('权限不足,无法执行批量操作!');
}
}
// 执行批量操作
// ...
}7. 权限缓存优化
权限检查结果会被缓存,提高性能:
// 权限检查会自动使用缓存
// 如果权限配置发生变化,需要清除缓存
// 系统会在权限配置更新时自动清除相关缓存8. 实际应用:多级权限控制
<?php
declare(strict_types=1);
namespace app\admin\controller;
use think\admin\Controller;
use think\admin\service\AdminService;
use think\admin\model\SystemUser;
/**
* 系统用户管理
* @class User
* @package app\admin\controller
*/
class User extends Controller
{
/**
* 系统用户管理
* @auth true
* @menu true
*/
public function index()
{
$this->title = '系统用户管理';
$this->issuper = AdminService::isSuper();
SystemUser::mQuery()->layTable(function () {
// 根据权限显示不同的操作按钮
$this->canEdit = AdminService::isSuper() || auth('admin/user/edit');
$this->canDelete = AdminService::isSuper() || auth('admin/user/remove');
});
}
/**
* 编辑系统用户
* @auth true
*/
public function edit()
{
$id = input('id');
// 非超级管理员只能编辑自己的资料
if (!AdminService::isSuper() && $id != AdminService::getUserId()) {
$this->error('只能编辑自己的资料!');
}
SystemUser::mForm('form');
}
/**
* 删除系统用户
* @auth true
*/
public function remove()
{
// 只有超级管理员可以删除用户
if (!AdminService::isSuper()) {
$this->error('只有超级管理员可以删除用户!');
}
// 防止删除系统超级账号
$ids = str2arr(input('id', ''));
if (in_array('10000', $ids)) {
$this->error('系统超级账号禁止删除!');
}
SystemUser::mDelete();
}
}权限管理注意事项:
- 权限节点命名:遵循
应用/控制器/方法格式 - 权限缓存:权限配置更新后会自动清除缓存
- 超级管理员:拥有所有权限,无需配置
- 权限继承:子权限需要父权限支持
- 菜单关联:菜单节点必须与权限节点对应
- 安全建议:重要操作建议在代码中再次验证权限
❓ 常见问题
Q1:权限节点不生效?
可能原因:
- 注解配置错误
- 权限节点未刷新
- 用户未分配权限
解决方法:
// 1. 检查注解配置
/**
* @auth true // 确保注解正确
*/
public function index() { }
// 2. 刷新权限节点
// 系统管理 → 权限管理 → 刷新节点
// 3. 检查用户权限
// 系统管理 → 用户管理 → 编辑用户 → 检查权限分配Q2:菜单不显示?
可能原因:
- 菜单节点配置错误
- 用户没有对应权限
- 菜单未启用
解决方法:
// 1. 检查菜单节点配置
// 菜单节点必须与权限节点对应
// 例如:菜单节点 admin/user/index 对应权限节点 admin/user/index
// 2. 检查用户权限
// 确保用户拥有菜单对应的权限节点
// 3. 检查菜单状态
// 系统管理 → 菜单管理 → 检查菜单是否启用Q3:如何检查用户权限?
方法1:使用 auth() 函数
// 检查用户是否有权限
if (auth('admin/user/index')) {
// 有权限
} else {
// 无权限
}方法2:使用 AdminService
use think\admin\service\AdminService;
// 检查是否为超级管理员
if (AdminService::isSuper()) {
// 超级管理员拥有所有权限
}
// 获取当前用户ID
$userId = AdminService::getUserId();方法3:在模板中使用
<!-- 使用权限判断显示/隐藏按钮 -->
<!--{if auth('admin/user/remove')}-->
<button data-action="{:url('remove')}">删除</button>
<!--{/if}-->Q4:如何实现按钮级权限控制?
方法1:在控制器中判断
public function index()
{
// 根据权限显示不同的操作按钮
$this->canEdit = auth('admin/user/edit');
$this->canDelete = auth('admin/user/remove');
return $this->fetch();
}方法2:在模板中判断
<!-- 编辑按钮 -->
<!--{if auth('admin/user/edit')}-->
<button data-action="{:url('edit')}">编辑</button>
<!--{/if}-->
<!-- 删除按钮 -->
<!--{if auth('admin/user/remove')}-->
<button data-action="{:url('remove')}">删除</button>
<!--{/if}-->Q5:如何忽略某个应用的权限检查?
配置 rbac_ignore:
// config/app.php
return [
// 忽略 RBAC 权限检查的应用
'rbac_ignore' => ['index', 'wap', 'api'],
];注意事项:
- 被忽略的应用不会进行权限检查
- 所有用户都可以访问被忽略的应用
- 建议只忽略确实不需要权限控制的应用
Q6:如何修改超级管理员账号名?
方法1:配置文件修改
// config/app.php
return [
'super_name' => 'admin', // 改为其他名称,如 'superadmin'
];方法2:数据库修改
-- 修改用户表中的用户名
UPDATE system_user SET username = 'superadmin' WHERE username = 'admin';注意事项:
- 修改后需要使用新名称登录
- 建议不要频繁修改超级管理员账号名
- 确保至少有一个超级管理员账号
Q7:权限节点如何自动生成?
系统自动生成规则:
// 控制器:app\admin\controller\User
// 方法:index()
// 生成的节点:admin/user/index
// 规则:
// 1. 应用名:从命名空间获取 app\admin\controller → admin
// 2. 控制器名:去掉 Controller 后缀 User → user
// 3. 方法名:直接使用 index → index
// 4. 完整节点:admin/user/index刷新权限节点:
系统管理 → 权限管理 → 刷新节点Q8:如何实现多级权限控制?
示例:需要多个权限才能执行操作
/**
* 批量操作(需要多个权限)
* @auth true
*/
public function batch()
{
// 检查是否拥有批量操作所需的所有权限
$requiredNodes = [
'admin/user/edit',
'admin/user/state',
];
foreach ($requiredNodes as $node) {
if (!auth($node)) {
$this->error('权限不足,无法执行批量操作!');
}
}
// 执行批量操作
// ...
}Q9:权限缓存如何清除?
自动清除:
- 权限配置更新后会自动清除缓存
- 用户权限分配后会自动清除缓存
手动清除:
# 清除所有缓存
php think clear
# 或删除缓存目录
rm -rf runtime/cache/*Q10:如何实现权限继承?
示例:子权限需要父权限支持
/**
* 编辑用户(需要查看权限)
* @auth true
*/
public function edit()
{
// 检查是否有查看权限
if (!auth('admin/user/index')) {
$this->error('需要先拥有查看权限!');
}
// 检查是否有编辑权限
if (!auth('admin/user/edit')) {
$this->error('权限不足!');
}
// 执行编辑操作
// ...
}