PHP 怎么PHP 访问控制列表

wen PHP项目 2

本文目录导读:

PHP 怎么PHP 访问控制列表

  1. 基于角色的简单 ACL(推荐新手使用)
  2. 数据库驱动的 ACL 系统
  3. 使用现有库:phpCAS(更专业)
  4. 完整的企业级 ACL 实现
  5. 性能优化技巧
  6. 选择建议

在 PHP 中实现访问控制列表(ACL,Access Control List)有多种方式,从简单的硬编码到基于数据库的动态权限系统,以下是几种常见的实现方法:

基于角色的简单 ACL(推荐新手使用)

<?php
class SimpleACL {
    private $roles = [
        'guest' => ['view'],
        'user' => ['view', 'create', 'edit'],
        'admin' => ['view', 'create', 'edit', 'delete', 'manage']
    ];
    private $userRole;
    public function __construct($role = 'guest') {
        $this->userRole = $role;
    }
    public function hasPermission($permission) {
        return in_array($permission, $this->roles[$this->userRole]);
    }
    public function checkAccess($permission) {
        if (!$this->hasPermission($permission)) {
            throw new Exception("权限不足");
        }
        return true;
    }
}
// 使用示例
$user = new SimpleACL('user');
if ($user->hasPermission('create')) {
    echo "可以创建文章";
}
?>

数据库驱动的 ACL 系统

数据库表结构

-- 用户表
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50),
    role_id INT
);
-- 角色表
CREATE TABLE roles (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50)
);
-- 权限表
CREATE TABLE permissions (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    description TEXT
);
-- 角色-权限关联表
CREATE TABLE role_permissions (
    role_id INT,
    permission_id INT,
    PRIMARY KEY (role_id, permission_id)
);

PHP 实现

<?php
class DBAcl {
    private $db;
    private $cache = [];
    public function __construct($dbConnection) {
        $this->db = $dbConnection;
    }
    public function getUserPermissions($userId) {
        // 使用缓存避免重复查询
        if (isset($this->cache[$userId])) {
            return $this->cache[$userId];
        }
        $stmt = $this->db->prepare("
            SELECT p.name 
            FROM permissions p
            JOIN role_permissions rp ON p.id = rp.permission_id
            JOIN users u ON u.role_id = rp.role_id
            WHERE u.id = ?
        ");
        $stmt->execute([$userId]);
        $permissions = $stmt->fetchAll(PDO::FETCH_COLUMN);
        $this->cache[$userId] = $permissions;
        return $permissions;
    }
    public function checkPermission($userId, $permissionName) {
        $permissions = $this->getUserPermissions($userId);
        return in_array($permissionName, $permissions);
    }
}
// 使用示例
$acl = new DBAcl($pdo);
if ($acl->checkPermission(1, 'article.create')) {
    echo "用户有创建文章的权限";
}
?>

使用现有库:phpCAS(更专业)

安装

composer require casbin/casbin

使用示例

<?php
require 'vendor/autoload.php';
use Casbin\Enforcer;
// 创建权限模型
$enforcer = new Enforcer('path/to/model.conf', 'path/to/policy.csv');
// 检查权限
if ($enforcer->enforce('alice', 'data1', 'read')) {
    echo "alice 可以读取 data1";
} else {
    echo "权限不足";
}
// 添加权限
$enforcer->addPermissionForUser('alice', 'data1', 'write');
// 获取用户所有权限
$permissions = $enforcer->getPermissionsForUser('alice');
?>

完整的企业级 ACL 实现

<?php
class AccessControlList {
    private $rules = [];
    private $user;
    public function __construct($user) {
        $this->user = $user;
        $this->loadRules();
    }
    private function loadRules() {
        // 从配置文件或数据库加载规则
        $this->rules = [
            'articles' => [
                'view' => ['*'], // 所有角色
                'create' => ['admin', 'editor'],
                'edit' => ['admin', 'editor'],
                'delete' => ['admin']
            ],
            'users' => [
                'view' => ['admin'],
                'manage' => ['admin']
            ]
        ];
    }
    public function isAllowed($resource, $action) {
        if (!isset($this->rules[$resource][$action])) {
            return false;
        }
        $allowedRoles = $this->rules[$resource][$action];
        if (in_array('*', $allowedRoles)) {
            return true;
        }
        return in_array($this->user->role, $allowedRoles);
    }
    public function requirePermission($resource, $action) {
        if (!$this->isAllowed($resource, $action)) {
            throw new PermissionDeniedException("权限不足");
        }
        return true;
    }
}
// 中间件使用示例
class AuthMiddleware {
    public function handle($request, $next) {
        $acl = new AccessControlList($request->user);
        // 检查当前路由的权限
        $resource = $request->route['resource'];
        $action = $request->route['action'];
        try {
            $acl->requirePermission($resource, $action);
            return $next($request);
        } catch (PermissionDeniedException $e) {
            return response()->json(['error' => '权限不足'], 403);
        }
    }
}
?>

性能优化技巧

<?php
class OptimizedACL {
    private static $instance;
    private $permissionsCache = [];
    private $cacheTimeout = 3600; // 1小时
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    // 使用 Redis 缓存
    public function checkPermissionWithRedis($userId, $permission) {
        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);
        $cacheKey = "acl:user:{$userId}:{$permission}";
        // 检查缓存
        if ($redis->exists($cacheKey)) {
            return (bool)$redis->get($cacheKey);
        }
        // 数据库查询
        $result = $this->queryDatabase($userId, $permission);
        // 设置缓存
        $redis->setex($cacheKey, $this->cacheTimeout, $result ? 1 : 0);
        return $result;
    }
}
?>

选择建议

  1. 小型项目:使用基于角色的简单 ACL(方法1)
  2. 中型项目:使用数据库驱动的 ACL(方法2)
  3. 大型/企业级项目:使用专业库如 phpCAS(方法3)
  4. 需要高性能:添加 Redis 缓存(方法5)

推荐从简单方法开始,根据项目需求逐步升级,权限系统宁严勿松,后期放宽比收紧容易得多。

抱歉,评论功能暂时关闭!