Использование Zend ACL в Codeigniter

Я - большой фанат CodeIgniter, но хотя, этот фреймворк очень хорош собой даже "из коробки", до начала разработки приложения на нем, я всегда добавляю в него несколько библиотек. Одна из них - класс для работы с ACL. Раньше я использовал в своих проектах простой класс, написанный мною, но не так давно решил перейти на довольно функциональный класс из фреймворка Zend (и встроить его в CodeIgniter, само собой). И теперь хочу поделиться этим опытом с моими читателями.

Скачайте последнюю версию Zend framework

Создайте папку Zend в /system/application/libraries.

Скопируйте Acl, Acl.php и Exception.php из фреймворка в нее

Создайте файл Zacl.php в папке libraries и скопируйте в него приведенный ниже код.

Добавьте 'zacl' в массив $autoload['libraries'] в /system/application/config/autoload.php.

Содержимое файла Zacl.php

  1. <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
  2.  
  3. class Zacl
  4. {
  5. var $CI;
  6. function __construct()
  7. {
  8. $this->CI =& get_instance();
  9. set_include_path(get_include_path() . PATH_SEPARATOR . BASEPATH . "application/libraries");
  10. require_once(APPPATH . '/libraries/Zend/Acl.php');
  11. require_once(APPPATH . '/libraries/Zend/Acl/Role.php');
  12. require_once(APPPATH . '/libraries/Zend/Acl/Resource.php');
  13. $this->acl = new Zend_Acl();
  14. $this->acl->addRole(new Zend_Acl_Role('default'));
  15. $query = $this->CI->db->get('tbl_aclresources');
  16. foreach($query->result() AS $row){
  17. $this->acl->add(new Zend_Acl_Resource($row->resource));
  18. if($row->default_value == 'true'){
  19. $this->acl->allow('default', $row->resource);
  20. }
  21. }
  22. $this->CI->db->order_by("roleorder", "ASC");
  23. $query = $this->CI->db->get('tbl_aclroles');
  24. foreach($query->result() AS $row){
  25. $role = (string)$row->name;
  26. $this->acl->addRole(new Zend_Acl_Role($role), 'default');
  27. $this->CI->db->from('tbl_acl');
  28. $this->CI->db->join('tbl_aclresources', 'tbl_acl.resource_id = tbl_aclresources.id');
  29. $this->CI->db->where('type', 'role');
  30. $this->CI->db->where('type_id', $row->id);
  31. $subquery = $this->CI->db->get();
  32. foreach($subquery->result() AS $subrow){
  33. if($subrow->action == "allow"){
  34. $this->acl->allow($role, $subrow->resource);
  35. } else {
  36. $this->acl->deny($role, $subrow->resource);
  37. }
  38. }
  39. $this->CI->db->from('tbl_users');
  40. $this->CI->db->where('roleid', $row->id);
  41. $userquery = $this->CI->db->get();
  42. foreach($userquery->result() AS $userrow){
  43. $this->acl->addRole(new Zend_Acl_Role($userrow->user), $role);
  44. $this->CI->db->from('tbl_acl');
  45. $this->CI->db->join('tbl_aclresources', 'tbl_acl.resource_id = tbl_aclresources.id');
  46. $this->CI->db->where('type', 'user');
  47. $this->CI->db->where('type_id', $userrow->userid);
  48. $usersubquery = $this->CI->db->get();
  49. foreach($usersubquery->result() AS $usersubrow){
  50. if($usersubrow->action == "allow"){
  51. $this->acl->allow($userrow->user, $usersubrow->resource);
  52. } else {
  53. $this->acl->deny($userrow->user, $usersubrow->resource);
  54. }
  55. }
  56. }
  57. }
  58. }
  59. // проверка имеет ли роль доступ к ресурсу
  60. function check_acl($resource, $role = '')
  61. {
  62. if (!$this->acl->has($resource))
  63. {
  64. return 1;
  65. }
  66. if (empty($role)) {
  67. if (isset($this->CI->session->userdata['user'])) {
  68. $role = $this->CI->session->userdata['user'];
  69. }
  70. }
  71. if (empty($role)) {
  72. return false;
  73. }
  74. return $this->acl->isAllowed($role, $resource);
  75. }
  76. }

Теперь вы очень легко можете проверить наличие доступа к ресурсу:

  1. // проверка доступа к ресурсу 'dummy' залогиненым пользователем
  2. if ($this->zacl->check_acl('dummy')){
  3. ...
  4. }
  5. // проверка доступа к ресурсу 'manage_users' роли 'admin'
  6. if ($this->zacl->check_acl('manage_users', 'admin')) {
  7. ...
  8. }

Думаю код вполне понятный, но на всякий случай я прикладываю еще и структуру таблиц.

  1. CREATE TABLE IF NOT EXISTS `tbl_acl` (
  2. `id` int(11) NOT NULL AUTO_INCREMENT,
  3. `type` enum('role','user') NOT NULL,
  4. `type_id` int(11) NOT NULL,
  5. `resource_id` int(11) NOT NULL,
  6. `action` enum('allow','deny') NOT NULL,
  7. PRIMARY KEY (`id`)
  8. ) ENGINE=MyISAM DEFAULT;
  9.  
  10. CREATE TABLE IF NOT EXISTS `tbl_aclresources` (
  11. `id` int(11) NOT NULL AUTO_INCREMENT,
  12. `resource` varchar(255) NOT NULL,
  13. `description` longtext NOT NULL,
  14. `aclgroup` varchar(255) NOT NULL,
  15. `aclgrouporder` int(11) NOT NULL,
  16. `default_value` enum('true','false') NOT NULL,
  17. PRIMARY KEY (`id`)
  18. ) ENGINE=MyISAM DEFAULT;
  19.  
  20. CREATE TABLE IF NOT EXISTS `tbl_aclroles` (
  21. `id` int(11) NOT NULL AUTO_INCREMENT,
  22. `name` varchar(255) NOT NULL,
  23. `roleorder` int(11) NOT NULL,
  24. PRIMARY KEY (`id`)
  25. ) ENGINE=MyISAM DEFAULT;
  26.  
  27. INSERT INTO `tbl_aclroles` (`id`, `name`, `roleorder`) VALUES
  28. (1, 'Admin', 1),
  29. (2, 'User', 2),
  30. (3, 'Guest', 3);
  31.  
  32. CREATE TABLE IF NOT EXISTS `tbl_users` (
  33. `userid` int(11) NOT NULL AUTO_INCREMENT,
  34. `user` longtext NOT NULL,
  35. `pass` longtext NOT NULL,
  36. `firstname` longtext NOT NULL,
  37. `prefix` longtext NOT NULL,
  38. `lastname` longtext NOT NULL,
  39. `gender` enum('m','f') NOT NULL,
  40. `roleid` int(11) NOT NULL,
  41. `mail` longtext NOT NULL,
  42. PRIMARY KEY (`userid`)
  43. ) ENGINE=MyISAM DEFAULT;

Отредактировав свои контроллеры, настроив права доступа и изменив модель авторизации, вы получите превосходную заготовку для создания нового приложения на CodeIgniter

4 Responses to Использование Zend ACL в Codeigniter

  1. gravatar

    Спасибо большое!

  2. gravatar

    Спасибо большое за разъяснение.
    Если Вы большой фанат CI наверняка уже присматривались к Fuelphp ? Понравился ли он?

  3. gravatar

    @Денис, нет, не присматривался. зато потихоньку перехожу на Symfony2. В целом хочу уходить от CI, всё меньше и меньше он мне нравиться

  4. gravatar

    Надеюсь, Вы созреете и напишите отзыв - субъективный взгляд при переходе на Симфони с CI
    Рано или поздно многие начинают писать сложные проекты и ломают голову на что перейти.

Leave a Reply