在 CodeIgniter(CI)專案中,若需實作輕量級的角色基礎存取控制(RBAC),善用 CI 內建的 Hook 機制是不錯的選擇。本文示範如何透過 post_controller_constructor Hook 攔截請求,配合設定檔定義權限規則,達成簡易 ACL 功能。
編輯 application/config/config.php,將 enable_hooks 設為 TRUE:
$config['enable_hooks'] = TRUE;
編輯 application/config/hooks.php,掛載 Acl 類別的 auth 方法:
$hook['post_controller_constructor'] = array(
'class' => 'Acl',
'function' => 'auth',
'filename' => 'acl.php',
'filepath' => 'hooks'
);
重點:post_controller_constructor 代表在 Controller 建構子執行後、方法執行前介入,適合做權限檢查。其他可用時間點請參考官方文件。
建立 application/config/acl.php,以陣列定義角色對應的允許存取「控制器 => 方法」對照表:
$config['AUTH'] = array(
'SUPER_ADMIN' => array(
'admin' => array('index', 'logout'),
),
'ADMIN' => array(
'admin' => array('index', 'logout'),
),
'GUEST' => array(
'admin' => array('index', 'logout'),
),
);
實務上請依專案實際角色與功能調整,且陣列鍵名需為 $config['AUTH'] 方便載入。
建立 application/hooks/acl.php:
<?php
class Acl {
private $url_model;
private $url_method;
private $CI;
public function __construct() {
$this->CI =& get_instance();
$this->CI->load->library('session');
$this->url_model = $this->CI->uri->segment(1); // 控制器
$this->url_method = $this->CI->uri->segment(2); // 方法
}
public function auth() {
$user = $this->CI->session->userdata('USER');
if (empty($user)) $user->status = 0; // 未登入視為 0
$this->CI->load->config('acl');
$AUTH = $this->CI->config->item('AUTH');
if (in_array($user->status, array_keys($AUTH))) {
$controllers = $AUTH[$user->status];
if (in_array($this->url_model, array_keys($controllers))) {
if (!in_array($this->url_method, $controllers[$this->url_model])) {
show_error('您無權訪問該功能!<a href="'.site_url('admin/logout').'">返回</a>');
}
} else {
show_error('您無權訪問該模組!<a href="'.site_url('admin/logout').'">返回</a>');
}
} else {
show_error('錯誤的用戶類型!<a href="'.site_url('admin/logout').'">返回</a>');
}
}
}
$this->CI =& get_instance(); 取得 CI 超級物件,才能在 Hook 類別中存取 CI 資源(Session、Config、URI 等)。show_error。掌握此架構後,即可依專案需求彈性擴充更完善的權限管理系統。