Thứ Bảy, 16 tháng 10, 2010

Dùng Zend_ACL trong CodeIgniter

Qua tìm hiểu thì : Codeigniter không có thư việc cho ACL
Mặt khác cũng không có ACL plugin nào cho CI đủ tốt .

Vì vậy giải pháp dùng Zend_ACL là khả thi nhất .

Zend ACL là một thư viện nhỏ trong Zend Framework . Chúng chỉ có khoảng 4 file .

Rất thích hợp để dưa vào CI .

  1. Download thư viện Zend framework

  2. Tạo thư mục  Zend trong thư mục   /system/application/libraries của CodeIgniter .

  3. Copy  thư mục  Acl , file  Acl.php và file Exception.php của Zend framework vào thư mục Zend vừa tạo .

  4. Tạo file  Zacl.php trong thư mục libraries .<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
    class Zacl
    {
    // Set the instance variable
    var $CI;


    function __construct()
    {
    // Get the instance
    $this->CI =& get_instance();

    // Set the include path and require the needed files
    set_include_path(get_include_path() . PATH_SEPARATOR . BASEPATH . "application/libraries");
    require_once(APPPATH . '/libraries/Zend/Acl.php');
    require_once(APPPATH . '/libraries/Zend/Acl/Role.php');
    require_once(APPPATH . '/libraries/Zend/Acl/Resource.php');
    $this->acl = new Zend_Acl();

    // Set the default ACL
    $this->acl->addRole(new Zend_Acl_Role('default'));
    $query = $this->CI->db->get('tbl_aclresources');
    foreach($query->result() AS $row){
    $this->acl->add(new Zend_Acl_Resource($row->resource));
    if($row->default_value == 'true'){
    $this->acl->allow('default', $row->resource);
    }
    }
    // Get the ACL for the roles
    $this->CI->db->order_by("roleorder", "ASC");
    $query = $this->CI->db->get('tbl_aclroles');
    foreach($query->result() AS $row){
    $role = (string)$row->name;
    $this->acl->addRole(new Zend_Acl_Role($role), 'default');
    $this->CI->db->from('tbl_acl');
    $this->CI->db->join('tbl_aclresources', 'tbl_acl.resource_id = tbl_aclresources.id');
    $this->CI->db->where('type', 'role');
    $this->CI->db->where('type_id', $row->id);
    $subquery = $this->CI->db->get();
    foreach($subquery->result() AS $subrow){
    if($subrow->action == "allow"){
    $this->acl->allow($role, $subrow->resource);
    } else {
    $this->acl->deny($role, $subrow->resource);
    }
    }
    // Get the ACL for the users
    $this->CI->db->from('tbl_users');
    $this->CI->db->where('roleid', $row->id);
    $userquery = $this->CI->db->get();
    foreach($userquery->result() AS $userrow){
    $this->acl->addRole(new Zend_Acl_Role($userrow->user), $role);
    $this->CI->db->from('tbl_acl');
    $this->CI->db->join('tbl_aclresources', 'tbl_acl.resource_id = tbl_aclresources.id');
    $this->CI->db->where('type', 'user');
    $this->CI->db->where('type_id', $userrow->userid);
    $usersubquery = $this->CI->db->get();
    foreach($usersubquery->result() AS $usersubrow){
    if($usersubrow->action == "allow"){
    $this->acl->allow($userrow->user, $usersubrow->resource);
    } else {
    $this->acl->deny($userrow->user, $usersubrow->resource);
    }
    }
    }
    }
    }

    // Function to check if the current or a preset role has access to a resource
    function check_acl($resource, $role = '')
    {
    if (!$this->acl->has($resource))
    {
    return 1;
    }
    if (empty($role)) {
    if (isset($this->CI->session->userdata['user'])) {
    $role = $this->CI->session->userdata['user'];
    }
    }
    if (empty($role)) {
    return false;
    }
    return $this->acl->isAllowed($role, $resource);
    }
    }

  5. Nếu muốn Zacl tự động load vào CI thì code vào trong file autoload , cái này nên cân nhắc kỹ :D .

  6. Cách dùng : $this->zacl->check_acl gọi hàm này :D


7. DB script
CREATE TABLE IF NOT EXISTS `tbl_acl` (
`id` int(11) NOT NULL auto_increment,
`type` enum('role','user') NOT NULL,
`type_id` int(11) NOT NULL,
`resource_id` int(11) NOT NULL,
`action` enum('allow','deny') NOT NULL,
PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT;

CREATE TABLE IF NOT EXISTS `tbl_aclresources` (
`id` int(11) NOT NULL auto_increment,
`resource` varchar(255) NOT NULL,
`description` longtext NOT NULL,
`aclgroup` varchar(255) NOT NULL,
`aclgrouporder` int(11) NOT NULL,
`default_value` enum('true','false') NOT NULL,
PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT;

CREATE TABLE IF NOT EXISTS `tbl_aclroles` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`roleorder` int(11) NOT NULL,
PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT;

INSERT INTO `tbl_aclroles` (`id`, `name`, `roleorder`) VALUES
(1, 'Admin', 1),
(2, 'User', 2),
(3, 'Guest', 3);

CREATE TABLE IF NOT EXISTS `tbl_users` (
`userid` int(11) NOT NULL auto_increment,
`user` longtext NOT NULL,
`pass` longtext NOT NULL,
`firstname` longtext NOT NULL,
`prefix` longtext NOT NULL,
`lastname` longtext NOT NULL,
`gender` enum('m','f') NOT NULL,
`roleid` int(11) NOT NULL,
`mail` longtext NOT NULL,
PRIMARY KEY  (`userid`)
) ENGINE=MyISAM DEFAULT;

2 nhận xét: