php实现rbac
PHP实现RBAC(基于角色的访问控制)
RBAC(Role-Based Access Control)是一种常见的权限管理模型,通过角色分配权限,用户通过角色间接拥有权限。以下是PHP实现RBAC的核心步骤和代码示例。
数据库设计
创建以下表结构存储RBAC数据:
用户表(users)
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE,
password VARCHAR(255)
);
角色表(roles)
CREATE TABLE roles (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) UNIQUE,
description TEXT
);
权限表(permissions)
CREATE TABLE permissions (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) UNIQUE,
description TEXT
);
用户角色关联表(user_roles)

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)
);
角色权限关联表(role_permissions)
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)
);
核心功能实现
1. 检查用户权限
function hasPermission($userId, $permissionName) {
// 查询用户是否拥有指定权限
$sql = "SELECT COUNT(*) FROM role_permissions rp
JOIN permissions p ON rp.permission_id = p.id
JOIN user_roles ur ON rp.role_id = ur.role_id
WHERE ur.user_id = ? AND p.name = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$userId, $permissionName]);
return $stmt->fetchColumn() > 0;
}
2. 分配角色给用户

function assignRoleToUser($userId, $roleName) {
// 获取角色ID
$roleId = $pdo->query("SELECT id FROM roles WHERE name = '$roleName'")->fetchColumn();
// 分配角色
$pdo->prepare("INSERT INTO user_roles (user_id, role_id) VALUES (?, ?)")
->execute([$userId, $roleId]);
}
3. 为角色分配权限
function assignPermissionToRole($roleName, $permissionName) {
// 获取角色和权限ID
$roleId = $pdo->query("SELECT id FROM roles WHERE name = '$roleName'")->fetchColumn();
$permissionId = $pdo->query("SELECT id FROM permissions WHERE name = '$permissionName'")->fetchColumn();
// 分配权限
$pdo->prepare("INSERT INTO role_permissions (role_id, permission_id) VALUES (?, ?)")
->execute([$roleId, $permissionId]);
}
中间件实现(用于路由保护)
创建权限检查中间件:
function checkPermission($permission) {
return function ($request, $response, $next) use ($permission) {
if (!hasPermission($_SESSION['user_id'], $permission)) {
return $response->withStatus(403)->write('Forbidden');
}
return $next($request, $response);
};
}
路由中使用中间件:
$app->get('/admin', function ($request, $response) {
return $response->write('Admin Dashboard');
})->add(checkPermission('admin_access'));
缓存优化
为提高性能,可缓存用户权限:
function getUserPermissions($userId) {
$cacheKey = "user_permissions_{$userId}";
if ($permissions = cache_get($cacheKey)) {
return $permissions;
}
$sql = "SELECT p.name FROM permissions p
JOIN role_permissions rp ON p.id = rp.permission_id
JOIN user_roles ur ON rp.role_id = ur.role_id
WHERE ur.user_id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$userId]);
$permissions = $stmt->fetchAll(PDO::FETCH_COLUMN);
cache_set($cacheKey, $permissions, 3600);
return $permissions;
}
最佳实践
- 使用预处理语句防止SQL注入
- 实现权限继承(角色继承其他角色的权限)
- 定期清理未使用的角色和权限
- 记录权限变更日志
- 提供界面管理角色和权限
这个实现提供了RBAC的核心功能,可根据实际需求进行扩展。对于大型系统,可以考虑使用现有的权限管理库如Laravel的Gate和Policy系统。






