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?
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
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');
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' );
}
}
}
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);
}
}
Related
I'am trying call custom library function witch should return inputed values back to form, but I'am geting error.
enter image description here
Controler:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Guest extends CI_Controller {
public function __construct(){
parent::__construct();
error_reporting(E_ALL ^ (E_NOTICE));
$this->load->helper(array('form', 'url', 'date'));
$this->load->library('form_validation', 'uri');
$this->load->model('dayData');
$this->load->library('session');
$this->load->library('guest');
}
public function index(){
$this->login();
}
public function dataToView($data, $viewFile){
$this->load->view('template/header');
if($viewFile != ''){
$this->load->view('user/' . $viewFile, $data);
}
$this->load->view('template/footer');
}
public function login(){
$this->dataToView($data, 'guest/login');
}
public function registration(){
if($this->input->post('registrationSubmit') !== null) {
//$this->form_validation->set_error_delimiters('<div class="alert alert-warning" role="alert">', '</div>');
$this->config->load('form_validation');
$this->form_validation->set_rules($this->config->item('registrationValidation'));
if($this->form_validation->run() == FALSE){
var_dump($this->guest->registrationPost());
$this->dataToView($data, 'guest/registration');
} else {
echo "string";
}
} else {
$this->dataToView($data, 'guest/registration');
}
}
}
Library:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Guest {
protected $CI;
public function __construct(){
// Assign the CodeIgniter super-object
$this->CI =& get_instance();
//$this->CI->load->model('Guest');
$this->CI->lang->load('error', 'english');
}
public function registrationPost(){
$result = array('name' => $this->CI->input->post('name'),
'nickName' => $this->CI->input->post('nickName'),
'email' => $this->CI->input->post('email'));
return $result;
}
}
There is a naming conflict between the controller and the custom class. They should not have the same name.
You have duplicate class names. The controller class name is Guest and the library class name is also Guest.
When CodeIgniter goes to load the Guest library, it will skip over it and log a debug message. https://github.com/bcit-ci/CodeIgniter/blob/develop/system/core/Loader.php#L1032
I suggest renaming your library to something else, Registration perhaps?
I am new to CodeIgniter framework. I am using 2.1.4 version. I designed a simple login form, with a javascript validation, and the home page of a site. Can you please help me to understand how to declare session , and how to destroy the session on clicking signout link.
controller file of login page ( to load the view page login.php ):-
class Login extends CI_Controller {
function __construct() {
parent::__construct();
$this->load->helper('url');
}
function index(){
$this->load->view('login');
}
function success() {
redirect ('home');
}
}
The controller file home.php for the view home.php
class Home extends CI_Controller {
// local constructor will be overriding the one in the parent controller class
// for using a constructor in any of my Controllers
function __construct() {
parent::__construct();
}
public function index()
{
$this->load->view('home');
}
}
I have designed the view page home.php, and gave the signout link:-
<div class="logout">Signout</div>
For initializing the session, i need to know, what all constructor changes/ config changes need, and the method of session destoy.
To start session library, Go to application/config/config.php and change the below line:
$autoload['libraries'] = array('session');
It would be better if you start your session in the autoload.php. To destroy session you would use :
$this->session->sess_destroy();
To set session :
$newdata = array(
'username' => 'johndoe',
'email' => 'johndoe#some-site.com',
'logged_in' => TRUE
);
$this->session->set_userdata($newdata);
here is an controller... first of all u need to declare a session so that you have two choice to declare one is Go to application/config/config.php change the code as
$autoload['libraries'] = array('session');
and follow this following method (controller)
class Login extends CI_Controller{
function __construct(){
parent::__construct();
$this->load->library('session');
}
function index(){
$this->load->view('login');
}
function success() {
$user=$this->input->post('user');
$psw=$this->input->post('pswd');
$this->load->model('validation');
$result=$this->validation->useraccess($user,$psw);
if($result)
{
$this->session->set_userdata('username', $user); //setting session
redirect ('home');
}
else
{
$this->index();
}
}
function logout()
{
$this->session->unset_userdata('username');
redirect('login','refresh');
}
}
this is model where validation done
Class Validation extends CI_Model{
function __construct(){
parent::__construct();
}
function useraccess($user,$pswd)
{
$query = $this->db->query("select * from user where username='$user' AND password='$pswd'");
foreach ($query->result_array() as $row)
{
if($row['username']==$user AND $row['password']==$pswd)
{
return true;
}
else
{
return false;
}
}
}
}
here is a view
login page
create 2 text box and 1 submit button and declare form action as
localhost/index.php/login/success
for logut
localhost/index.php/login/logout
I am creating a website with static pages and admin editable news and content. I want to separate admin and public views. Is this a good way to separate views or Is there a better one you can suggest. I want basically same views but only admin will have a form based text area to change content of a topic.
MY_Controller.php :
class MY_Controller extends CI_Controller {
protected $data = array();
function __construct() {
parent::__construct();
}
class Admin_Controller extends MY_Controller {
function __construct()
{
parent::__construct();
// Check login, load back end dependencies
}
function render_page($view) {
if( ! $this->input->is_ajax_request() )
{
$this->load->view('templates/header', $this->data);
}
$this->load->view($view, $this->data);
if( ! $this->input->is_ajax_request() )
{
$this->load->view('templates/menu');
$this->load->view('templates/footer', $this->data);
}
}
}
class Public_Controller extends MY_Controller {
function __construct()
{
parent::__construct();
// Check login, load back end dependencies
}
function render_page($view) {
if( ! $this->input->is_ajax_request() )
{
$this->load->view('templates/header', $this->data);
}
$this->load->view($view, $this->data);
if( ! $this->input->is_ajax_request() )
{
$this->load->view('templates/menu');
$this->load->view('templates/footer', $this->data);
}
}
}
}
If the admin view is common across pages, you could load it as a view at an appropriate spot on your page, eg.
if($is_admin){
$this->load->view('admin_toolbar');
}else{
$this->load->view('generic_toolbar');
}
Or, if the admin view is not common across pages, you could include a flag in the data you send to the page.
(In controller)
$this->data['is_admin'] = true;
(In view)
if($is_admin):
//output admin related html here.
endif
I have the below code:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Login extends MY_Controller
{
function __construct()
{
parent::__construct();
$this->load->model('users/user_model');
$this->load->library('form_validation');
}
function _load_login_page()
{
$this->load->model('sysconfig/sysconfig_model');
$a = $this->sysconfig_model->get_sysconfig();
$row = $a[0];
$this->lang->load('klas',$row->sysconfig_language);
$data['sys_name'] = $row->sysconfig_system_name;
$data['template_name'] = $row->systemplate_name;
$data['css_script'] = base_url().'assets/'.$row->systemplate_name;
if($row->sysconfig_maintenance === 'Y')
{
$this->load->view('sysconfig/maintenance',$data);
}
else {
$this->load->view('login',$data);
}
}
function index()
{
$this->form_validation->set_rules('username', 'Username', 'trim|required|max_length[12]|xss_clean|callback_check_auth');
$this->form_validation->set_rules('password','Password','trim|required');
if($this->form_validation->run($this) == FALSE)
{
$this->_load_login_page();
} else {
redirect('welcome','refresh');
}
}
function check_auth()
{
if($this->user_model->authentication())
{
return TRUE;
}
$this->form_validation->set_message('check_auth',$this->lang->line('invalid_username'));
return FALSE;
}
?>
user_model.php
<?php
class User_Model extends CI_Model
{
function authentication()
{
$this->db->where('useracc_id', $this->input->post('username'));
$this->db->where('useracc_password', md5($this->input->post('password')));
$q = $this->db->get('base_useracc');
if($q->num_rows() == 1)
{
$session_data = array('isUserLogged'=>TRUE);
$this->session->set_userdata($session_data);
return TRUE;
}
}
?>
From here we can see if the user didn't fill the username and password fields, it will show the error and everything works as expected. The problem is, if the user provides an invalid username or password, the error message won't show.
for the information, I already put $lang['invalid_username'] = 'Invalid username or password'; on the language file.
I am doing this using the HMVC technique. Please help me.
You don't seem to be passing any data to your callback function. Callback functions expect the value of the input field to be passed as a parameter. I don't think you can make this work as a form validation callback be because the authentication method presumably needs to know both the password and the username. At present you're not passing any data into your check_auth method or indeed onwards to your user_model->authentication() method. That is why form_validation is ignoring it.
Rather than calling check_auth as a callback, why not run the form_validation first (this is really what it's for - checking the data is correct and sanitised) and then pass the values from your form to your check_auth function as part of an if statement. You will not be able to use the form_validation set_message method to display errors but I think this is a cleaner approach.
To summarise, use the form_validation to check the data you are receiving is ok and display relevant messages if it is not. Authenticating a user based on that information is a separate procedure that I don't think belongs with validation. Do you see the difference?
from the HMVC wiki page :
When using form validation with MX you will need to extend the CI_Form_validation class as shown below, before assigning the current controller as the $CI variable to the form_validation library. This will allow your callback methods to function properly. (This has been discussed on the CI forums also). ie:
<?php
/** application/libraries/MY_Form_validation **/
class MY_Form_validation extends CI_Form_validation
{
public $CI;
}
<?php
class Xyz extends MX_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('form_validation');
$this->form_validation->CI =& $this;
}
}
im trying to create a new lib which will auto load each time a controller is loaded and authenticate to see if a user is logged in
I’m auto loading the script and its loading fine how-ever it doesn’t seam to authenticate
My Lib
class Authentication {
var $CI;
function Authenication() {
$this->CI =& get_instance();
$this->CI->load->library('session');
$is_logged_in = $this->CI->session->userdata('is_logged_in');
if(!isset($is_logged_in) || $is_logged_in != true)
{
echo 'You don\'t have permission to access this page. Login';
die();
}
}
}
Any suggestions are greatly appreciated
I see what you are trying to do and I would suggest a different approach.
Create MY_Controller and put it in the core folder. Here is a basic representation of what should be in that file.
class Public_Controller extends CI_Controller
{
// The data array holds all of the information to be displayed in views
public $data = array();
function __construct()
{
parent::__construct();
// Authentication library handles sessions and authentication, etc...
$this->load->library('Authentication');
$this->data['account']['is_logged_in'] = $this->authenication->is_logged_in();
}
}
class Auth_Controller extends Public_Controller
{
function __construct()
{
parent::__construct();
if ( !$this->data['account']['is_logged_in'] )
{
redirect('user/login', 'location');
}
}
}
If you do it this way then for controllers that require authentication you can just extend Auth_Controller otherwise extend Public_Controller.