首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 後台權限分配系統:基於欄目 ID 的 RBAC 簡易實現

     編輯:PHP 綜合知識

核心設計思想

採用「管理員 ↔ 欄目 ID 列表」映射模式:

  1. 超管創建管理員時,勾選可訪問的欄目
  2. 將勾選的欄目 ID 以逗號分隔字符串存入 admin.pres 字段
  3. 登錄後解析權限字符串,生成導航菜單與接口白名單

數據表結構

CREATE TABLE `rc_admin` (
    `admin_id`   INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `admin_name` VARCHAR(32)  NOT NULL,
    `pres`       VARCHAR(512) NOT NULL DEFAULT '', -- 欄目ID列表: 1,3,5,12
    PRIMARY KEY (`admin_id`),
    UNIQUE KEY `uk_name` (`admin_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

權限分配頁面(含前端渲染)

<?php
// 分配頁面:admin_perm.php
$pdo = new PDO('mysql:host=localhost;dbname=study', 'root', 'root');
$pdo->exec('SET NAMES utf8');

// 獲取所有欄目(實際項目應從配置或菜單表讀取)
$modules = [
    ['id' => 1,  'group' => '獵頭服務', 'items' => ['添加獵頭企業','獵頭企業','獵頭職位','企業申請','獵頭申請管理']],
    ['id' => 6,  'group' => '懸賞招聘', 'items' => ['添加懸賞企業','管理懸賞企業','管理懸賞職位']],
];

// 處理提交
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $prom = $_POST['prom'] ?? [];
    $pres = implode(',', array_map('intval', $prom));
    $stmt = $pdo->prepare("INSERT INTO rc_admin (admin_name, pres) VALUES (?, ?)");
    $stmt->execute(['admin', $pres]);
    echo $stmt->rowCount() ? 'success' : 'error';
    exit;
}

// 獲取當前管理員權限(編輯時回填)
$currentPres = [];
$stmt = $pdo->prepare("SELECT pres FROM rc_admin WHERE admin_name = 'admin'");
$stmt->execute();
if ($row = $stmt->fetch()) {
    $currentPres = array_map('intval', explode(',', $row['pres']));
}
?>
<form method="post">
<table>
<?php foreach ($modules as $mod): ?>
    <tr>
        <td><strong><?= htmlspecialchars($mod['group']) ?></strong></td>
        <td>
            <?php foreach ($mod['items'] as $idx => $item): 
                $cid = $mod['id'] + $idx;
                $checked = in_array($cid, $currentPres) ? 'checked' : '';
            ?>
                <label>
                    <input type="checkbox" name="prom[]" value="<?= $cid ?>" <?= $checked ?>>
                    <?= htmlspecialchars($item) ?>
                <label><br>
            <?php endforeach; ?>
        </td>
    </tr>
<?php endforeach; ?>
</table>
<button type="submit">提交權限</button>
</form>

權限驗證中間件(核心邏輯)

<?php
// auth_check.php - 每個受保護頁面頂部引入
session_start();
$pdo = new PDO('mysql:host=localhost;dbname=study', 'root', 'root');
$pdo->exec('SET NAMES utf8');

// 假設當前登錄用戶 ID 存於 $_SESSION['admin_id']
$adminId = $_SESSION['admin_id'] ?? 0;
$currentModuleId = (int)($_GET['module_id'] ?? 0); // 當前訪問的欄目 ID

if (!$adminId || !$currentModuleId) {
    exit('未授權訪問');
}

$stmt = $pdo->prepare("SELECT pres FROM rc_admin WHERE admin_id = ?");
$stmt->execute([$adminId]);
$pres = $stmt->fetchColumn() ?? '';

// 權限判斷:當前欄目 ID 是否在允許列表中
$allowed = array_map('intval', explode(',', $pres));
if (!in_array($currentModuleId, $allowed)) {
    exit('權限不足:無法訪問該欄目');
}

// 通過驗證,繼續執行業務邏輯
?>

左側導航動態渲染

<?php
// nav_render.php
$allowed = array_map('intval', explode(',', $pres));
$allModules = [ /* 同分配頁面的 $modules 結構 */ ];

foreach ($allModules as $mod) {
    $groupItems = [];
    foreach ($mod['items'] as $idx => $item) {
        $cid = $mod['id'] + $idx;
        if (in_array($cid, $allowed)) {
            $groupItems[] = "<a href='?module_id=$cid'>$item</a>";
        }
    }
    if ($groupItems) {
        echo "<div class='nav-group'><h4>{$mod['group']}</h4>";
        echo implode('<br>', $groupItems);
        echo "</div>";
    }
}
?>

優缺點與擴展建議

優點缺點
實現極簡,無需額外關係表權限粒度僅到「欄目」,無法控制「增刪改查」
查詢極快(單表單字段)字符串存儲難以利用索引,用戶量大時性能下降
適合中小型後台項目不支援角色繼承、多角色組合

進階擴展方向

  1. 標準 RBAC:admin_role + role_permission + permission(resource, action)
  2. 位掩碼權限:用整數二進制位表示 CRUD,單字段存 4 權限
  3. JWT + Casbin:微服務架構下的分布式授權方案

簡易版適合快速交付,複雜業務建議遷移至標準 RBAC 模型。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved