CodeIgniter Forums

Full Version: MX_ACL - Access Control library
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2

El Forum

[eluser]wiredesignz[/eluser]
Code:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* MX_Acl - Access Control library
*
* Save this file as application/libraries/MX_Acl.php
* $autoload['libraries'] = array('mx_acl', ... );
* $config['cache_path'] must be set
*
* @copyright     Copyright (c) Wiredesignz & Maxximus 2009-04-20
* @version        0.12
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
class MX_Acl
{    
    var $uri, $config, $session, $cache_path;
    
    function __construct($config = array()) {
        $ci =& get_instance();    
        $ci->load->helper('url');        
        $ci->load->library('session');
        
        $this->uri =& $ci->uri;
        $this->config = $config;
        $this->session =& $ci->session;
        $this->cache_path = $ci->config->item('cache_path');
        
        /* previous flashdata is available to views */
        $ci->load->vars($config['error_var'], $this->session->flashdata($config['error_var']));
        
        /* run the access control check now */
        ($config['check_uri']) AND $this->check_uri();
    }
    
    /**
     * Check the current uri and user privileges against the cached ACL array
     * Redirect if access is denied
     *
     * @return void
     */
    function check_uri() {
        
        /* Load the cached access control list or show error */
        (is_file($cached_acl = $this->cache_path.'mx_acl'.EXT)) OR show_error($this->config['error_msg']);
        
        $acl = include $cached_acl;
        
        /* Match current url to access list */
        if (is_array($acl) AND $acl = $this->match_uri($this->current_uri(), $acl)) {
            
            /* Check session group against access level group */
            $allow_access = (bool)(in_array($this->session->userdata($this->config['session_var']), $acl['allowed']));
                
             /* Additional check to allow IP addresses in range */
            if ( ! $allow_access AND isset($acl['ipl'])) $allow_access = $this->check_ip($acl['ipl']);
                
            if ($allow_access == FALSE)    {
                
                /* Set a return url into the session */
                $this->session->set_userdata('return_url', $this->uri->uri_string());
                
                /* set the error message... */
                $error_msg = (isset($acl['error_msg'])) ? $acl['error_msg'] : $this->config['error_msg'];
                    
                /* set a flash message... */
                $this->session->set_flashdata($this->config['error_var'], $error_msg);        
                    
                /* redirect to absolute url */
                die(header("Location: ".$acl['error_uri'], TRUE, 302));
            }
        }
    }
    
    /**
     * Return the access control profile for a given url
     *
     * @return string
     * @param string $current_uri
     * @param array  $acl
     */
    function match_uri($current_uri, $acl) {
        if (array_key_exists($current_uri, $acl)) {
            return $acl[$current_uri];            
        } else {
            if ($pos = strripos($current_uri, '/')) {
                return $this->match_uri(substr($current_uri, 0, $pos), $acl);
            }
        }
    }

    /**
     * Returns the first 2 or 3 segments from the current uri
     *
     * @return string
     */
    function current_uri() {
        if ($this->uri->total_segments() == 2)    {        
            return $this->uri->slash_rsegment(1).$this->uri->rsegment(2);
        }
        return $this->uri->slash_rsegment(1).$this->uri->slash_rsegment(2).$this->uri->rsegment(3);
    }

    /**
     * Checks the remote IP address against the specified $ipl array
     *
     * @return bool
     * @param array $ipl
     * @param string $remote_ip[optional]
     */    
     function check_ip($ipl, $remote_ip = NULL) {
        
        /* Convert ip address into a double (for lousy OSes)*/
        $remote_ip = floatval(ip2long(($this->session->userdata('ip_address'))));
        
        /* Loop through the ip list array */
        foreach ($ipl as $allowed_ip) {
            
            /* Replace '*' (for IP ranges) with a suitable range number */
            $min = str_replace("*", "0", $allowed_ip);        
            $max = str_replace("*", "255", $allowed_ip);

            /* Check for a match */
            if (($remote_ip >= floatval(ip2long($min))) AND ($remote_ip <= floatval(ip2long($max)))) {
                return TRUE;
            }
        }
    }
}

El Forum

[eluser]wiredesignz[/eluser]
Code:
&lt;?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* MX_Acl configuration
*
* Save this file as application/config/mx_acl.php
*/
$config = array(
    'check_uri'    => TRUE,
    'error_var'    => 'error',
    'error_msg'    => 'You don\'t have sufficient access rights to view this page!',
    'session_var'  => 'role_id',
);
Code:
&lt;?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* This is the cached access control list
*
* save this file as {cache_path}/mx_acl.php
*/
return array(
    'setting/update' => array(                       // the "module/controller/method" to protect
        'allowed'    => array(1),                    // the allowed user role_id array
        'ipl'        => array('127.0.0.1'),          // the allowed IP range array
        'error_uri'  => site_url('secure/setting'),  // the url to redirect to on failure
        'error_msg'  => 'You do not have permission to update this page!',
    ),
    'page/update'    => array(
        'allowed'    => array(1, 2, 3),
        'ipl'        => array('127.0.0.0','127.0.0.*'),
        'error_uri'  => (isset($_SERVER['HTTP_REFERER'])) ? $_SERVER['HTTP_REFERER'] : site_url('secure/page'),
        'error_msg'  => 'You do not have permission to update this page!',
    ),
);

El Forum

[eluser]johnwbaxter[/eluser]
Show off....

El Forum

[eluser]ray73864[/eluser]
oooook then, and for the uninitiated, what's it all mean in layman terms? in particular, how about a doco page or something that explains it Smile

El Forum

[eluser]Johan André[/eluser]
This might be what I've looked for!

Could you please post a (very) quick example of how to use it in controllers?

El Forum

[eluser]wiredesignz[/eluser]
Hi Johan Andre,

MX_Acl does not require any interaction from your controllers.

MX_Acl checks the URI and session userdata "role_id" (and IP address) against its cached access control list and automatically redirects if access is denied to that user.

Session flashdata is set with your access denied "error_msg" and session userdata "return_url" is set with the current URI in case you wish to return to the same location after a login procedure.

Most of the configuration variable names are customizable to suit your own application.

Hope this helps.

El Forum

[eluser]Thorpe Obazee[/eluser]
Nice library!

But is there anyway this could be converted to interact with the database instead of a file? I 'believe' that's much better and very much preferred.

El Forum

[eluser]wiredesignz[/eluser]
Actually, the much preferred way would be for you to create the cached access control list file each time you add or edit the acl information in the database.

El Forum

[eluser]Thorpe Obazee[/eluser]
But wouldn't that be like working 'twice' since you have to edit two things?

El Forum

[eluser]wiredesignz[/eluser]
The script you use to edit the database would create the file. File access is much faster than database. And not all applications have a full blown user management system, so MX_Acl lists can be added/updated manually also.

Best of both worlds.

EDIT:

Another possibility to investigate would be an "access_rules" method in your controller, similar to the method used by Yii framework.

The MX_Acl library would then call the current controller to obtain the acl array rather than use a cached file.
Pages: 1 2