-- 資源表
CREATE TABLE aclresources (
rsid VARCHAR(64) PRIMARY KEY,
access INT(4) DEFAULT 0, -- 0:無人 1:所有人 2:有角色 3:無角色 4:指定角色
`desc` VARCHAR(240),
created_at INT(10), updated_at INT(10)
) CHARSET=utf8;
-- 角色表
CREATE TABLE aclroles (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
rolename VARCHAR(32) UNIQUE,
`desc` VARCHAR(240),
created_at INT(10), updated_at INT(10)
) CHARSET=utf8;
-- 資源-角色關聯
CREATE TABLE ref_aclresources_aclroles (
rsid VARCHAR(64),
role_id INT UNSIGNED,
PRIMARY KEY (rsid, role_id)
) CHARSET=utf8;
-- 用戶-角色關聯
CREATE TABLE ref_users_aclroles (
user_id INT UNSIGNED,
role_id INT UNSIGNED,
PRIMARY KEY (user_id, role_id)
) CHARSET=utf8;
-- 用戶表
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(128) UNIQUE,
password VARCHAR(64),
nickname VARCHAR(32),
roles VARCHAR(240), -- 可冗餘儲存角色 ID 字串
created_at INT(10), updated_at INT(10)
) CHARSET=utf8;
class AclBase {
const NOBODY = 0;
const EVERYONE = 1;
const HAS_ROLE = 2;
const NO_ROLE = 3;
const ALLOCATE_ROLES = 4;
public $tbResources = 'aclresources';
public $tbRoles = 'aclroles';
public $tbRefResourcesRoles = 'ref_aclresources_aclroles';
public $tbRefUsersRoles = 'ref_users_aclroles';
// 建立/修改/刪除資源、角色、關聯等 CRUD 方法略...
// 重點:allocateRolesForResource, allocateResourcesForRole, allocateRolesForUser
}
function aclVerify($rsid, $user = null) {
if (empty($rsid)) return false;
$rs = aclGetResource($rsid); // 從快取/DB 取得資源定義
if (!$rs) return false; // 未定義資源預設拒絕
$access = AclBase::formatAccessValue($rs['access']);
// 1. 全域規則
if ($access == AclBase::EVERYONE) return true;
if ($access == AclBase::NOBODY) return false;
// 2. 取得當前用戶角色
if (empty($user)) $user = $_SESSION['SI-SysUser'] ?? null;
if (empty($user)) return false;
$userRoles = empty($user['roles']) ? [] : explode(';', $user['roles']);
$hasRoles = !empty($userRoles);
// 3. 角色存在性規則
if ($access == AclBase::NO_ROLE) return !$hasRoles;
if ($access == AclBase::HAS_ROLE) return $hasRoles;
// 4. 指定角色規則:檢查用戶角色與資源允許角色的交集
if ($access == AclBase::ALLOCATE_ROLES) {
foreach ($userRoles as $rid) {
if (aclGetRefResourcesRoles($rsid, $rid)) return true;
}
}
return false;
}
將三張核心表載入記憶體/檔案快取(aclGetACT、aclRebuildACT),驗證時直接查快取,避免每請求查資料庫。