Welcome Guest, Not a member yet? Register   Sign In
Using Zend_Auth and Zend_ACL with CI
#11

[eluser]zackwragg[/eluser]
I have actually changed my mind and implemented an edited version of Fresh Auth as this seemed quite straightforward and accomplished what I wanted.

I am still playing with the authorisation stuff in my head and not sure which way to go. With the full-blown ACL stuff I am a little concerned about the memory-intensity of loading up the whole ACL model each time a user logs in and then having to store this for each user (seems like needless duplication). I am thinking of using Zend_ACL to implement an RBAC model so that on log in I can easily pull out only that users permissions and store that, thus reducing the memory load. Does anyone have any thoughts on this?

Thanks
#12

[eluser]thurting[/eluser]
[quote author="zackwragg" date="1227115562"]
I am still playing with the authorisation stuff in my head and not sure which way to go. With the full-blown ACL stuff I am a little concerned about the memory-intensity of loading up the whole ACL model each time a user logs in and then having to store this for each user (seems like needless duplication).
Thanks[/quote]

It would be and that is crazy. Build the ACL once and cache it somewhere - Zend_Acl is serializable. Whenever an administrative user modifies the ACL, flush the cache. Store user information (id, name, role, etc.) in a session, and you have a super efficient and lightweight ACL scheme.
#13

[eluser]zackwragg[/eluser]
I am not sure what you mean with this. In my head at the moment, if you serialize it and store it somewhere (I assume this would most likely be a database?) you would then need to retrieve it from that place and store it in memory to access it. I am guessing from what you are saying that this would not be the correct way to deal with it, but I can't see how I could access the ACL without it being in memory which would mean that at user login it would need to be brought into the app and loaded into memory to query it.

Any chance you could help me clarify this a little more for myself.

Thanks for the help
#14

[eluser]thurting[/eluser]
The way I have done it in the past, I store all of my users, roles, rights, and role-right relationships in the database. In the bootstrap I check to see if the ACL object exists in cache. If not, I build the ACL from the data in my database and store it in cache (ZF ships with adapters for multiple backends - to start, I suggest using File). I then store it in a Registry object so I can access it from anywhere in the app. I create a preDispatch method in my action controllers that compare the user's role (I store this in session) to the ACL. If the user is allowed, the action fires. If not, they are redirected. I also have a web based UI to update the ACL tables in the DB. When these are updated, I recreate the ACL and overwrite the cache.
#15

[eluser]SirSickboy[/eluser]
[quote author="zackwragg" date="1226793705"]
Primarily, I am wondering if there is some way to use the CI database classes or if I should use the Zend DB libraries for the authentication. However, if anyone can give me any info on their implementation Zend_Auth/Zend_ACL, or any words of encouragement that would be great.

Any help with this would greatly much appreciated.[/quote]

Hi zackwragg

I've used Zend_ACL successfully in my code igniter app and it's fairly straightforward to get up and running. I'm in the process of writing up about my experiences on my blog so can pm you a link when i get it done (probably this weekend).
#16

[eluser]zackwragg[/eluser]
SirSickBoy, that would be awesome if you could.

Thurting, I'll have a read up on Zend (and CI) caching and try to figure that out but what you say make a lot of sense. Think I just need to get the theory behind the two caching systems straight in my head.

I totally appreciate all the help guys. Thanks.
#17

[eluser]zackwragg[/eluser]
Right, I had to take a little time off this but have been back on it for a little bit and have my ACL library developed, but not I am stuck again.

Basically, I wrote my ACL class extending Zend_ACl and in the constructor of my class I loaded all the roles, resources and permissions into the ACL object so that it is ready to query. Now, I want to attach this to the front controller so that, on loading a page, the ACL object is queried an can decide if the current user has permission to access the controller and function in the URI (controller being the resource and the function being the privilege in the ACL object).

As I want to be able to access the CI instance, I have hooked this to the post_controller_constructor hook. In the hook I include the ACL library, the constructor is called and the ACL roles, resources and permissions are loaded. The problem I have is that on calling the isAllowed method of the ACL object, it tells me that none of the roles I have just loaded into it are there.

I am sure this must be something simple that I am missing here so if anyone can spot it that would be a massive help. I have posted my code below. If you need any more info, please feel free to ask.

Thanks for the help.

ACL.php (my ACL library class)
Code:
class ACL extends Zend_ACL
{
    var $config;
    var $CI;

    function __construct($config)
    {
        $this->CI =& get_instance();
        $this->CI->load->helper('url');
        $this->CI->load->database();

        $this->config = $config;

        if( file_exists($this->config['acl_cached_file']) )
        {

        }
        else
        {
            $this->acl = new Zend_ACL();

            // Get roles
            $this->CI->db->order_by('id', 'ASC');
            $query = $this->CI->db->get($this->config['acl_db_roles_table']);
            $roles = $query->result();

            // Get users
/*            $CI->db->order_by('id', 'ASC');
            $query = $CI->db->get($this->config['acl_db_user_table']);
            $users = $query->result();
*/
            // Get resources
            $this->CI->db->order_by('id', 'ASC');
            $query = $this->CI->db->get($this->config['acl_db_resources_table']);
            $resources = $query->result();

            // Get permissions
            $query = $this->CI->db->get($this->config['acl_db_permissions_table']);
            $permissions = $query->result();

            // Set up the ACL object
            foreach ($roles as $role) { //Add the roles to the ACL
                $role_object = new Zend_Acl_Role($role->name);

                if($role->parent_id != null)
                {
                    error_log('this->acl->addRole('.$role->name.','.$role->parent_id.')');
                    $this->acl->addRole($role_object, $role->parent_id);
                }
                else
                {
                    error_log('this->acl->addRole('.$role->name.')');
                    $this->acl->addRole($role_object);
                    error_log(($this->acl->hasRole($role->name)) ? 'TRUE' : 'FALSE');
                }
            }

            foreach($resources as $resource)  //Add the resources to the ACL
            {
                   $resource_object = new Zend_Acl_Resource($resource->name);

                   if($resource->parent_id != null)
                {
                    $this->acl->add($resource_object, $resource->parent_id);
                }
                else
                {
                    $this->acl->add($resource_object);
                }
            }

            foreach($permissions as $perm)  //Add the permissions to the ACL
            {
                if( $perm->allow === 1 )
                {
                    $this->acl->allow( $perm->role, $perm->resource, $perm->privilege );
                }
                else
                {
                    $this->acl->deny( $perm->role, $perm->resource, $perm->privilege );
                }
            }

           // Serialize and cache the ACL object in a file
        }
    } // Acl()
}

ACL_Hook.php (my ACl hook)
Code:
class Acl_Hook
{
    var $CI;

    function initialise_acl()
    {
        $this->CI =& get_instance();
        $this->CI->load->library('acl');
        $this->CI->load->library('session');

        $resource = $this->CI->uri->segment(1);
        $privilege = $this->CI->uri->segment(2);

        if( $this->CI->session->userdata('logged_in') )  // if user is logged in then get roles
        {
            $role = $this->CI->session->userdata('role');
        }
        else  // Role is guest
        {
            $role = 'guest';
        }

        if( ! $this->CI->acl->isAllowed($role, $resource, $privilege) )
        {
            // Not allowed access so redirect
        }
    }
}
#18

[eluser]SirSickboy[/eluser]
Try disabling your hook and loading your acl library in your controller. Then, in your controller, have a look at the output from
Code:
var_dump($this->acl);)

I like the way you've rolled the action into your controller methods. It makes for a nice compact library.
#19

[eluser]zackwragg[/eluser]
Thanks, SirSickBoy.

I did the var_dump and it looks as if everything is fine with the setting of the ACL object. All my roles and resources are in there. However, there seems to be some duplication and there are also some parts in the var_dump where it says that the $_roleRegistry is null so this may be where my problem is coming from. The var_dump is too big to post into a message so I have uploaded it here if you want to take a look: http://www.darksummer.co.uk/var_dump.txt.

The error I am getting it from an uncaught exception (which I will deal with eventually once I Have solved the problem and it is below:

Code:
PHP Fatal error:  Uncaught exception 'Zend_Acl_Role_Registry_Exception' with message 'Role 'member' not found' in C:\\web\\ds\\system\\libraries\\Zend\\Acl\\Role\\Registry.php:132
Stack trace:
#0 C:\\web\\ds\\system\\libraries\\Zend\\Acl.php(687): Zend_Acl_Role_Registry->get('member')
#1 C:\\web\\ds\\system\\application\\libraries\\Acl.php(117): Zend_Acl->isAllowed('member', false, false)
#2 C:\\web\\ds\\system\\application\\hooks\\Acl_Hook.php(25): ACL->isAllowed('member', false, false)
#3 C:\\web\\ds\\system\\libraries\\Hooks.php(205): Acl_Hook->initialise_acl('')
#4 C:\\web\\ds\\system\\libraries\\Hooks.php(107): CI_Hooks->_run_hook(Array)
#5 C:\\web\\ds\\system\\codeigniter\\CodeIgniter.php(214): CI_Hooks->_call_hook('post_controller...')
#6 C:\\web\\ds\\index.php(115): require_once('C:\\web\\ds\\syste...')
#7 {main}  
   thrown in C:\\web\\ds\\system\\libraries\\Zend\\Acl\\Role\\Registry.php on line 132

I have also been looking through the Zend_ACL code to track the path through the code and everything (obviously) seems to be fine with it, so I am still a tad confused.
#20

[eluser]SirSickboy[/eluser]
Can you upload a sql dump of your roles, resources and permissions tables?

I'll have a go at importing it at my end and try and see where things are going wrong.




Theme © iAndrew 2016 - Forum software by © MyBB