本文目录导读:

我来详细介绍PHP动态权限的实现方案:
基于RBAC的权限模型
数据库表结构
-- 用户表
CREATE TABLE `users` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(50) UNIQUE NOT NULL,
`password` VARCHAR(255) NOT NULL,
`status` TINYINT DEFAULT 1,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 角色表
CREATE TABLE `roles` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`description` VARCHAR(255),
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 用户角色关联表
CREATE TABLE `user_roles` (
`user_id` INT,
`role_id` INT,
PRIMARY KEY (`user_id`, `role_id`),
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`),
FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`)
);
-- 权限表
CREATE TABLE `permissions` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`slug` VARCHAR(100) UNIQUE NOT NULL,
`description` VARCHAR(255),
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 角色权限关联表
CREATE TABLE `role_permissions` (
`role_id` INT,
`permission_id` INT,
PRIMARY KEY (`role_id`, `permission_id`),
FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`),
FOREIGN KEY (`permission_id`) REFERENCES `permissions`(`id`)
);
权限管理核心类
<?php
class PermissionManager {
private $db;
private $cache;
public function __construct($db) {
$this->db = $db;
$this->cache = [];
}
/**
* 获取用户所有权限
*/
public function getUserPermissions($userId) {
// 检查缓存
if (isset($this->cache[$userId])) {
return $this->cache[$userId];
}
$sql = "SELECT DISTINCT p.slug
FROM permissions p
INNER JOIN role_permissions rp ON p.id = rp.permission_id
INNER JOIN user_roles ur ON rp.role_id = ur.role_id
WHERE ur.user_id = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$userId]);
$permissions = $stmt->fetchAll(PDO::FETCH_COLUMN);
// 缓存结果
$this->cache[$userId] = $permissions;
return $permissions;
}
/**
* 检查用户是否有某个权限
*/
public function hasPermission($userId, $permissionSlug) {
$permissions = $this->getUserPermissions($userId);
return in_array($permissionSlug, $permissions);
}
/**
* 添加角色
*/
public function createRole($name, $description = '') {
$sql = "INSERT INTO roles (name, description) VALUES (?, ?)";
$stmt = $this->db->prepare($sql);
return $stmt->execute([$name, $description]);
}
/**
* 添加权限
*/
public function createPermission($name, $slug, $description = '') {
$sql = "INSERT INTO permissions (name, slug, description) VALUES (?, ?, ?)";
$stmt = $this->db->prepare($sql);
return $stmt->execute([$name, $slug, $description]);
}
/**
* 为用户分配角色
*/
public function assignRole($userId, $roleId) {
$sql = "INSERT INTO user_roles (user_id, role_id) VALUES (?, ?)";
$stmt = $this->db->prepare($sql);
$result = $stmt->execute([$userId, $roleId]);
// 清除缓存
unset($this->cache[$userId]);
return $result;
}
/**
* 为角色分配权限
*/
public function assignPermissionToRole($roleId, $permissionId) {
$sql = "INSERT INTO role_permissions (role_id, permission_id) VALUES (?, ?)";
$stmt = $this->db->prepare($sql);
return $stmt->execute([$roleId, $permissionId]);
}
}
权限中间件/拦截器
<?php
class AuthMiddleware {
private $permissionManager;
public function __construct($permissionManager) {
$this->permissionManager = $permissionManager;
}
/**
* 权限验证中间件
*/
public function requirePermission($permissionSlug) {
// 获取当前用户ID(从session或token获取)
$userId = $this->getCurrentUserId();
if (!$userId) {
header('HTTP/1.1 401 Unauthorized');
echo json_encode(['error' => '未登录']);
exit;
}
if (!$this->permissionManager->hasPermission($userId, $permissionSlug)) {
header('HTTP/1.1 403 Forbidden');
echo json_encode(['error' => '没有权限']);
exit;
}
return true;
}
/**
* 检查用户角色
*/
public function requireRole($roleName) {
$userId = $this->getCurrentUserId();
$sql = "SELECT r.name FROM roles r
INNER JOIN user_roles ur ON r.id = ur.role_id
WHERE ur.user_id = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$userId]);
$roles = $stmt->fetchAll(PDO::FETCH_COLUMN);
if (!in_array($roleName, $roles)) {
header('HTTP/1.1 403 Forbidden');
echo json_encode(['error' => '需要特定角色']);
exit;
}
}
private function getCurrentUserId() {
// 从session或token获取用户ID
session_start();
return $_SESSION['user_id'] ?? null;
}
}
使用示例
<?php
// 初始化
$db = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$permManager = new PermissionManager($db);
$auth = new AuthMiddleware($permManager);
// 1. 创建权限
$permManager->createPermission('创建文章', 'article.create', '允许用户创建新文章');
$permManager->createPermission('编辑文章', 'article.edit', '允许用户编辑文章');
$permManager->createPermission('删除文章', 'article.delete', '允许用户删除文章');
// 2. 创建角色
$permManager->createRole('管理员', '系统管理员');
$permManager->createRole('编辑者', '内容编辑者');
// 3. 为角色分配权限
$permManager->assignPermissionToRole(1, 1); // 管理员有创建权限
$permManager->assignPermissionToRole(1, 2); // 管理员有编辑权限
$permManager->assignPermissionToRole(1, 3); // 管理员有删除权限
$permManager->assignPermissionToRole(2, 1); // 编辑者有创建权限
$permManager->assignPermissionToRole(2, 2); // 编辑者有编辑权限
// 4. 为用户分配角色
$permManager->assignRole(1, 1); // 用户1是管理员
$permManager->assignRole(2, 2); // 用户2是编辑者
// 5. 在控制器中使用
class ArticleController {
public function create() {
global $auth;
$auth->requirePermission('article.create');
// 创建文章的逻辑
echo "文章创建成功";
}
public function edit($id) {
global $auth;
$auth->requirePermission('article.edit');
// 编辑文章的逻辑
echo "文章编辑成功";
}
public function delete($id) {
global $auth;
$auth->requirePermission('article.delete');
// 删除文章的逻辑
echo "文章删除成功";
}
}
高级特性
基于路由的权限控制
<?php
// 路由配置
$routes = [
'/admin' => ['permission' => 'admin.access', 'redirect' => '/login'],
'/admin/users' => ['permission' => 'user.manage'],
'/admin/articles/create' => ['permission' => 'article.create'],
'/admin/articles/edit/*' => ['permission' => 'article.edit'],
];
// 路由中间件
function routeMiddleware($uri) {
global $auth;
foreach ($routes as $pattern => $config) {
if (matchRoute($pattern, $uri)) {
$auth->requirePermission($config['permission']);
return true;
}
}
// 默认允许访问
return true;
}
function matchRoute($pattern, $uri) {
// 简单的路由匹配
$pattern = str_replace('*', '.*', $pattern);
return preg_match('#^' . $pattern . '$#', $uri);
}
权限缓存优化
<?php
class PermissionManagerWithRedis extends PermissionManager {
private $redis;
public function __construct($db, $redis) {
parent::__construct($db);
$this->redis = $redis;
}
public function getUserPermissions($userId) {
// 尝试从Redis缓存读取
$cacheKey = "user_permissions:{$userId}";
$cached = $this->redis->get($cacheKey);
if ($cached !== false) {
return json_decode($cached, true);
}
// 从数据库获取
$permissions = parent::getUserPermissions($userId);
// 存入Redis,设置过期时间
$this->redis->setex($cacheKey, 3600, json_encode($permissions));
return $permissions;
}
public function clearUserCache($userId) {
$cacheKey = "user_permissions:{$userId}";
$this->redis->del($cacheKey);
unset($this->cache[$userId]);
}
}
最佳实践
- 权限粒度设计:权限名使用模块.操作格式(如 article.create)
- 缓存策略:使用Redis/Memcached缓存用户权限列表
- 权限变更通知:权限变更时清除对应缓存
- 日志记录:记录权限验证日志用于审计
- 前端配合:前端根据权限动态显示/隐藏功能按钮
这个动态权限系统可以灵活地管理用户权限,支持角色和权限的动态分配和修改,适合各种规模的PHP应用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播