前言
FastAdmin 内置了完整的 RBAC(基于角色的访问控制)权限体系,支持细粒度的菜单管理、操作权限和数据权限控制。本文将深入讲解 FastAdmin 权限认证的工作原理和实际配置方法。
一、RBAC 权限模型概述
FastAdmin 的权限体系包含三个核心实体:
管理员(Admin)──→ 角色组(Group)──→ 权限规则(Rule)| 实体 | 数据表 | 说明 |
|---|---|---|
| 管理员 | fa_admin | 后台用户,每个用户属于一个或多个角色组 |
| 角色组 | fa_group | 角色定义,每个角色关联一组权限规则 |
| 权限规则 | fa_auth_rule | 权限节点,对应控制器的每个操作方法 |
二、权限认证流程
2.1 认证类 Auth
FastAdmin 的权限认证由 application/common/library/Auth.php 实现:
namespace app\common\library;
use think\Session;
use think\Cookie;
use app\admin\model\Admin as AdminModel;
class Auth
{
protected $logined = false; // 是否登录
protected $admin = null; // 当前管理员信息
protected $error = ''; // 错误信息
protected $requestUri = ''; // 当前请求 URL
// 检查是否已登录
public function isLogin()
{
if ($this->logined) {
return true;
}
$admin = Session::get('admin');
if (!$admin) {
return false;
}
// 验证管理员状态
$this->admin = AdminModel::get($admin['id']);
if (!$this->admin || $this->admin['status'] != 'normal') {
return false;
}
$this->logined = true;
return true;
}
// 检查权限
public function check($name = '')
{
if (!$this->isLogin()) {
return false;
}
// 超级管理员直接通过
if ($this->admin['id'] == 1) {
return true;
}
// 获取当前用户的所有权限规则
$rules = $this->getRuleList();
if (!$name) {
$name = strtolower($this->request->module() . '/'
. $this->request->controller() . '/' . $this->request->action());
}
$name = strtolower($name);
// 检查是否有匹配的权限
foreach ($rules as $rule) {
if ($this->checkRule($rule, $name)) {
return true;
}
}
return false;
}
}2.2 权限检查链路
请求进入 → Backend 控制器初始化
→ Auth::check() 检查当前 URL 是否有权限
→ 无权限 → 返回 403 / 跳转登录
→ 有权限 → 继续执行2.3 控制器中的权限注解
FastAdmin 通过注解方式声明权限节点:
// application/admin/controller/content/Article.php
namespace app\admin\controller\content;
use app\common\controller\Backend;
class Article extends Backend
{
// 默认不需要登录的方法
protected $noNeedLogin = [];
// 默认不需要权限验证的方法
protected $noNeedRight = [];
/**
* 文章列表
*/
public function index()
{
return parent::index();
}
/**
* 添加文章
*/
public function add()
{
return parent::add();
}
/**
* 编辑文章
*/
public function edit($ids = null)
{
return parent::edit($ids);
}
/**
* 删除文章
*/
public function del($ids = null)
{
return parent::del($ids);
}
}每个 public 方法自动注册为一个权限节点,格式为 content/article/index。
三、菜单管理
3.1 菜单结构
菜单存储在 fa_auth_rule 表中,采用树形结构:
-- 查看菜单结构
SELECT id, pid, name, title, type FROM fa_auth_rule ORDER BY weigh DESC;| 字段 | 说明 |
|---|---|
id | 节点 ID |
pid | 父节点 ID(0 为顶级) |
name | 权限规则名(URL 路径) |
title | 菜单显示名称 |
type | 类型:menu=菜单,file=操作节点 |
icon | 菜单图标(FontAwesome) |
ismenu | 是否在左侧菜单显示(1=显示) |
3.2 命令行生成菜单
# 根据控制器自动生成菜单
php think menu -c content/article
# 强制覆盖
php think menu -c content/article -f 13.3 后台手动管理菜单
进入 后台 → 权限管理 → 菜单规则,可以:
- 添加/编辑/删除菜单节点
- 拖拽排序
- 设置菜单图标
- 控制菜单是否显示
3.4 菜单与权限的关系
菜单规则(fa_auth_rule)
├── 内容管理 (ismenu=1, type=menu)
│ ├── 文章管理 (ismenu=1, type=menu)
│ │ ├── 查看 (ismenu=0, type=file) → content/article/index
│ │ ├── 添加 (ismenu=0, type=file) → content/article/add
│ │ ├── 编辑 (ismenu=0, type=file) → content/article/edit
│ │ └── 删除 (ismenu=0, type=file) → content/article/delismenu=1 的节点显示在左侧导航栏,ismenu=0 的是操作按钮权限。
四、角色组管理
4.1 创建角色组
进入 后台 → 权限管理 → 角色组:
- 点击"添加"
- 填写角色名称(如"内容编辑")
- 勾选该角色拥有的权限
- 保存
4.2 角色权限继承
角色组支持树形结构,子角色自动继承父角色的所有权限:
超级管理员(id=1,拥有所有权限)
├── 内容主管(拥有内容管理全部权限)
│ ├── 内容编辑(拥有文章增改权限,无删除权限)
│ └── 内容审核(拥有文章审核权限)
└── 系统管理员(拥有系统设置权限)4.3 数据权限
FastAdmin 支持基于角色组的数据隔离:
// 在控制器中启用数据权限
public function index()
{
// 只能查看自己创建的数据
$this->dataLimit = 'personal';
// 只能查看本角色组的数据
$this->dataLimit = 'auth';
// 自定义数据限制字段
$this->dataLimitField = 'admin_id';
return parent::index();
}数据权限模式说明:
| 模式 | 说明 |
|---|---|
null | 不限制,可查看所有数据 |
personal | 只能查看自己创建的数据 |
auth | 只能查看本角色组及子角色组的数据 |
五、API Token 认证
除了后台 Session 认证,FastAdmin 的 API 模块支持 Token 认证:
5.1 Token 生成
// application/api/controller/User.php
namespace app\api\controller;
use app\common\controller\Api;
use app\common\library\Token;
class User extends Api
{
// 登录获取 Token
public function login()
{
$username = $this->request->post('username');
$password = $this->request->post('password');
$admin = \app\admin\model\Admin::get(['username' => $username]);
if (!$admin || $admin->password != md5(md5($password) . $admin->salt)) {
$this->error('用户名或密码错误');
}
// 生成 Token
$token = Token::create($admin['id'], 'admin', 86400 * 7);
$this->success('登录成功', [
'token' => $token,
'admin' => $admin,
]);
}
}5.2 Token 验证中间件
// API 请求头携带 Token
// Authorization: Bearer xxx-xxx-xxx
// 在 API 控制器中验证
namespace app\api\controller;
class Order extends Api
{
// 需要登录的方法
protected $noNeedLogin = [];
public function list()
{
// $this->auth 已自动初始化
$adminId = $this->auth->id;
$orders = model('Order')->where('admin_id', $adminId)->select();
$this->success('获取成功', $orders);
}
}六、安全加固建议
6.1 密码安全
// FastAdmin 使用双重 MD5 加盐
// password = md5(md5(明文密码) . salt)
// 自定义更安全的加密方式
\app\admin\model\Admin::event('before_insert', function ($admin) {
$admin->salt = \fast\Random::alnum(8);
$admin->password = password_hash($admin->password, PASSWORD_BCRYPT);
});6.2 登录失败限制
FastAdmin 默认 5 次登录失败后锁定 15 分钟,可在配置中调整:
// application/extra/site.php
'login_failure_retry' => 5, // 最大失败次数
'login_failure_lock' => 900, // 锁定时间(秒)6.3 操作日志
所有后台操作自动记录到 fa_admin_log 表:
// 手动记录日志
\app\admin\model\AdminLog::record([
'title' => '手动操作文章',
'content' => '修改了文章ID:' . $id,
]);总结
FastAdmin 的权限体系基于标准 RBAC 模型,通过菜单规则表实现细粒度权限控制。核心要点:
- 权限规则对应控制器的每个方法,自动注册
- 角色组支持树形继承,子角色继承父角色权限
- 数据权限支持 personal 和 auth 两种模式
- API 模块通过 Token 实现无状态认证
评论 (0)