27

I have a controller, which maps to section of my site and all of the pages within it (methods) should only appear if the user is logged in. Otherwise they should be redirected back to a login screen.

To get it working I've just done this:

function index() {

    if ($this->session->userdata('logged_in')) {
        $this->load->view('main');

    } else {
        redirect('/login');
    }
}

function archive() {

    if ($this->session->userdata('logged_in')) {

and so on... repeating that check in each method. What's the simplest way of doing this check once for multiple-or-all methods in the controller?

1

4 Answers 4

53

You can run code in every method of a Controller by running it in the __construct() method:

function __construct()
{
    parent::__construct();
    if ( ! $this->session->userdata('logged_in'))
    { 
        // Allow some methods?
        $allowed = array(
            'some_method_in_this_controller',
            'other_method_in_this_controller',
        );
        if ( ! in_array($this->router->fetch_method(), $allowed)
        {
            redirect('login');
        }
    }
}

You can remove the "allowed" bits if you want to restrict access to the whole thing, but there are better ways to do this, like creating a base controller:

// Create file application/core/MY_Controller.php
class Auth_Controller extends CI_Controller {

    function __construct()
    {
        parent::__construct();
        if ( ! $this->session->userdata('logged_in'))
        { 
            redirect('login');
        }
    }
}

Then have your restricted controllers extend Auth_Controller instead of CI_Controller. Now your code will be run every time the controller is loaded.

More info on extending core classes: http://www.codeigniter.com/user_guide/general/core_classes.html#extending-core-class

Also of interest: http://php.net/manual/en/language.oop5.decon.php

Sign up to request clarification or add additional context in comments.

7 Comments

For redirect() to work the URL helper needs to be loaded: $this->load->helper('url');
You named your new controller's file MY_Controller.php, yet you named the class Auth_Controller. This should not work, right? I'm asking because I encountered something very strange: as long as I named my new controller (which extends the base controller) MY_Auth_Controller, and tried to use this as my controllers' base class, CodeIgniter kept crashing. When I named if just 'MY_Controller' it all worked well. Why is that?
@whage It's just how CI was built, it will autoload MY_Controller.php if it exists.
I'm using CI ver. 3.0.0. I tried the above code (#2, MY_Controller) and I get a blank page, no html. I noticed that on this page it says to save the MY_Controller in application/libraries/. Whatever the case, I'm gettin' no love!
@GregoryLewis for codeigniter 3 you can use my answer below.
|
6

For codeIgniter 3 I modified Wesley Murch's answer to this

// Create file application/core/MY_Controller.php

<?php 
defined('BASEPATH') OR exit('No direct script access allowed');
class MY_Controller extends CI_Controller {

function __construct()
{
    parent::__construct();
    $CI = & get_instance();
    $CI->load->library('session');
    $CI->load->helper('url');
    if ( !$this->session->userdata('logged_in'))
    { 
        redirect('login');
    }
}

}

Then in any controller to check authorization I used

class News extends MY_Controller { //code here }

If you use modules and different sessions for website users and admin users, you can use this code to perfectly redirect them to different login pages-

function __construct() {
    parent::__construct();
    $CI = & get_instance();
    $CI->load->library('session');
    $CI->load->helper('url');
   // echo "<pre>";print_r($this->router);echo "</pre>";

    /**
     * if webmaster then check admin session else check user session
     * But there may be some classes's method that doesn't requires login hence it is also need to check if
     * current request is for those methods before checking session
     */
    //to use $this->config->item('webmaster_name') this you have to define 
    // $config['webmaster_name'] = "webmaster"; in config.php file

    if ($this->router->module == $this->config->item('webmaster_name')) {
        if (!$this->session->userdata('admin')['id']) {
            redirect($this->config->item('webmaster_name').'/login');
        }
    } else {
        if (!$this->session->userdata('user')['id']) {
            redirect('login');
        }
    }
}

If you also want users to allow to access some methods from any particular controller without being logged in you can use this code -

function __construct() {
    parent::__construct();
    $CI = & get_instance();
    $CI->load->library('session');
    $CI->load->helper('url');

    //echo "<pre>"; print_r($this->router);echo "</pre>"; //_pr($this->config->item('excluded_auth'));
    /**
     * if webmaster then check admin session else check user session
     * But there may be some classes's method that doesn't requires login hence it is also need to check if
     * current request is for those methods before checking session
     */
    if ($this->router->module == $this->config->item('webmaster_name')) {
        if (!$this->session->userdata('admin')['id']) {
            redirect($this->config->item('webmaster_name') . '/login');
        }
    } else {
        if (array_key_exists($this->router->class, $this->config->item('exclude_auth')) && in_array($this->router->method, $this->config->item('exclude_auth')[$this->router->class])) {
            //echo "escape this method. don not validate for a session";
        } else {
            if (!$this->session->userdata('user')['id']) {
                redirect('login');
            }
        }
    }
}

Note: You can define a custom config file for defining your excluded methods like as-

//save file in application/config/without_auth_methods.php

<?php
     defined('BASEPATH') OR exit('No direct script access allowed');
     $config['exclude_auth']['news']       = array('index', 'view');
     $config['exclude_auth']['users']      = array('index');

Comments

1

I use this function:

Then just call $this->isAuthorized from your controllers __construct.

It allows me to control what controllers are accessed and what methods are accessed too.

protected function isAuthorized()
{

    switch ( strtolower( $this->router->class ) )
    {
        case 'pages':
            $disallowLoggedOut = array( 'dashboard' );
            $disallowLoggedIn = array( 'index' );
        break;

        case 'users':
            $disallowLoggedOut = array( 'logout' );
            $disallowLoggedIn = array( 'register', 'login' );
        break;
    }

    if ( $this->session->userdata( 'loggedIn' ) ) 
    {       
        if ( in_array( $this->router->method, $disallowLoggedIn ) )
        {
            redirect( 'pages/dashboard' );
        }
    }
    else
    {       
        if ( in_array( $this->router->method, $disallowLoggedOut ) )
        {
            redirect( 'pages/index' );
        }
    }
}

Comments

0

Best way to deal such issue is to create a custom helper that should be called in every method of controller class e.g Go to application/helpers and create a file login_helper.php Paste the following code in the helper

<?php
 defined('BASEPATH') OR exit('no direct access');

 function isLogin($sessionType)
 {
   if(empty($_SESSION[$sessionType]))
         redirect(base_url('loginURL'));
 }

?>

Now load this helper into Controller's constructor.

application/controllers/Access.php

this way

defined('BASEPATH') OR exit('access denied');
class Access Extends CI_Controller
{
  funcrion __construct()
  {
    parent::__construct();
    $this->load->helper('login');
  }
  function home()
  {
    isLogin();
    $this->load->view('home_page);
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.