0

I made login app using codeigniter 3.0.1, i'm facing couple of problems. First is things are not working when i don't check the 'remember me' check box and it still logs the user in when i close the browser and open it again with direct link "localhost/ci_login_app/index.php/account" seems like

$config['sess_expire_on_close'] = TRUE;

have no effect on it :/

i have configured config.php like this

$config['sess_driver'] = 'database';
#$config['sess_cookie_name'] = 'ci_session';
$config['sess_expiration'] = 60*60*24*7;

$config['sess_expire_on_close'] = TRUE;

$config['sess_match_useragent'] = FALSE;

$config['sess_time_to_update'] = 300;

$config['sess_save_path'] = 'ci_sessions';

#$config['sess_use_database'] = TRUE;

$config['sess_match_ip'] = FALSE;
$config['sess_regenerate_destroy'] = TRUE;

This is my authentication file uesr_authentication.php

<?php

Class User_Authentication extends CI_Controller 
{

public function __construct() 
{
    parent::__construct();
}

// Show login page
public function index() 
{
    $this->load->view('layouts/header');
    $this->load->view('login_form');
    $this->load->view('layouts/footer');
}

public function user_login_process() 
{   

    $session_set_value = $this->session->all_userdata();

    // Check for remember_me data in retrieved session data
    if (isset($session_set_value['remember_me']) && $session_set_value['remember_me'] == "1") 
    {
        redirect('account');
    }       // Check for validation

    else{

        $this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean');
        $this->form_validation->set_rules('password', 'Password', 'trim|required|xss_clean');

        if ($this->form_validation->run() == FALSE) 
        {
            $this->load->view('layouts/header');
            $this->load->view('login_form');
            $this->load->view('layouts/footer');
        } 

        else 
        {
                $result = $this->model_login->login_user();

                switch ($result) 
                {
                    case 'authenticated':
                    redirect('account');

                        break;
                    case 'incorrect_password':
                        echo "Error loging in, password not correct...!";
                        $this->load->view('layouts/header');
                        $this->load->view('login_form');
                        $this->load->view('layouts/footer'); 

                        break;

                    case 'not_activated':
                        echo "Please activate your account before logging in...!";
                        $this->load->view('layouts/header');
                        $this->load->view('login_form');
                        $this->load->view('layouts/footer'); 

                        break;

                    case 'incorrect_username':
                        echo "Error loging in, password/username not correct...!";
                        $this->load->view('layouts/header');
                        $this->load->view('login_form');
                        $this->load->view('layouts/footer'); 

                        break;

                    default:
                        echo "Enter correct value, press backspace";
                        break;
                }
            }
        }

}

// Logout from admin page
public function logout() 
{

// Destroy session data
    $this->session->sess_destroy();
    $data['message_display'] = 'Successfully Logout';
    redirect('account');        
}
}
?>

This is my login.php controller

<?php
class Login extends CI_Controller
{
public function __construct()
{
    parent::__construct();
}

public function index()
{
    $this->load->view('layouts/header');
    $this->load->view('login_form');        
    $this->load->view('layouts/footer');
}

public function login_user()
{
    $this->form_validation->set_rules('username', 'User Name', 'trim|required');
    $this->form_validation->set_rules('password', 'Password ','trim|required');

    if($this->form_validation->run() === FALSE)
    {
        echo "Validations doesn't run correctly!<br>";
        $this->load->view('layouts/header');
        $this->load->view('login_form');
        $this->load->view('layouts/footer');       
    }
    else
    {
        $result = $this->model_login->login_user();

        switch ($result) {
            case 'logged_in':
                redirect('home');
                // $this->load->view('admin_page');


                break;
            case 'incorrect_password':
                echo "Error loging in, password not correct...!";
                $this->load->view('layouts/header');
                $this->load->view('login_form');
                $this->load->view('layouts/footer'); 

                break;

            case 'not_activated':
                echo "Please activate your account before logging in...!";
                $this->load->view('layouts/header');
                $this->load->view('login_form');
                $this->load->view('layouts/footer'); 

                break;

            case 'incorrect_username':
                echo "Error loging in, password/username not correct...!";
                $this->load->view('layouts/header');
                $this->load->view('login_form');
                $this->load->view('layouts/footer'); 

                break;

            default:
                # code...
                break;
        }
    }
}


public function reset_password()
{
    if (isset($_POST['email'])) 
    {
        # code...
        $this->form_validation->set_rules('email','Email Address','trim|required|valid_email');

        if ($this->form_validation->run() === FALSE) {
            # code...
            $this->load->view('layouts/header');
            $this->load->view('login/view_reset_password', array('error' => 'Please provide a valid email address'));
            $this->load->view('layouts/footer');
        }
        else
        {
            $email = trim($this->input->post('email'));
            $result = $this->model_login->email_exists($email);

            if ($result) 
            {
                $this->send_reset_password_email($email, $result);
                $this->load->view('layouts/header');
                $this->load->view('login/view_reset_password_sent', array('email' => $email));
                $this->load->view('layouts/footer');

            }
            else
            {

                $this->load->view('layouts/header');
                $this->load->view('login/view_login_reset_password_sent', array('error' => 'Email not registerd here'));
                $this->load->view('layouts/footer');
            }
        }
    }
    else
    {

        $this->load->view('layouts/header');
        $this->load->view('login/view_reset_password');
        $this->load->view('layouts/footer');
    }

}

public function reset_password_form($email, $email_code)
{
    if (isset($email) && isset($email_code)) 
    {
        #$email = trim($email);
        $email_hash = sha1($email.$email_code);
        $verified = $this->model_login->verify_reset_password_code($email, $email_code);

        if ($verified) 
        {
            $this->load->view('layouts/header');
            $this->load->view('login/view_update_password', 
                array(
                'email_hash'=>$email_hash,
                'email_code'=>$email_code,
                'email' => $email
                ));
            $this->load->view('layouts/footer');
        }
        else
        {
            echo "Can't get verified";
        }
    }
}

public function send_reset_password_email($email, $name)
{
    $this->load->library('email');
    $email_code = md5($this->config->item('salt').$name);

    $this->email->set_mailtype('html');
    $this->email->from($this->config->item('bot_email'),'reset password email');
    $this->email->to($email);
    $this->email->subject('Please reset your password');

    $message = "<!DOCTYPE html><html>
    <head>
        <title>Reset Password</title>
    </head>
    <body>";
    $message .= "<p> Dear '{$name}'</p>";
    $message .='<p> we want to help you reset your password! please <strong> <a href="'.base_url().'index.php/login/reset_password_form/'.$email.'/'.$email_code.'">Click here </a> </strong> to reset your password</p>';
    $message .="<p>Thank you</p>";
    $message .="</body></html>";

    $this->email->message($message);
    $this->email->send();
}

public function update_password()
{
    print_r($_REQUEST);
    $email = $this->input->post('email');
    $email_hash = $this->input->post('email_hash');
    $email_code = sha1($this->input->post('email').$this->input->post('email_code'));



    if (!isset($email,$email_hash) || ($email_hash != $email_code)) 
    {
        # code...
        die("Error updating password, unauthorize access");
    }

    $this->form_validation->set_rules('email_hash', 'Email Hash', 'trim|required');
    $this->form_validation->set_rules('email', 'Email', 'trim|required|valid_email');
    $this->form_validation->set_rules('new-password', 'password', 'trim|required|matches[new-password-again]');
    $this->form_validation->set_rules('new-password-again', 'password', 'trim|required');

    if ($this->form_validation->run() === FALSE) 
    {
        $this->load->view('layouts/header');
        $this->load->view('login/view_update_password');
        $this->load->view('layouts/footer');
    }
    else
    {
        $result = $this->model_login->update_password();

        if ($result) 
        {
            $this->load->view('layouts/header');
            $this->load->view('login/view_update_password_success');
            $this->load->view('layouts/footer');
        }

        else
        {
            $this->load->view('layouts/header');
            $this->load->view('login/view_update_password',array(
                'error' => 'problem updating your password please contact site admin xyz@abc.com' ));
            $this->load->view('layouts/footer');
        }
    }
}
}
?>

This is my model class model_login.php

<?php
class Model_login extends CI_Model
{

public function __construct()
{
    # code...
    parent::__construct();
}

public function login_user()
{
    $username = $this->input->post('username');
    #$password = $this->input->post('password');

    $remember = $this->input->post('remember_me');

    $userpass = sha1($this->config->item('salt').$this->input->post('password'));

    $sql = "SELECT * FROM users WHERE username = '{$username}'  LIMIT 1";
    $result = $this->db->query($sql);
    $row = $result->row();

    if($result->num_rows() == 1)
    {
        if($row->activated)
        {

            if ($row->password == $userpass) 
            {

                if ($remember) 
                {
                    $this->session->set_userdata('remember_me', TRUE);
                    $this->config->set_item('sess_expire_on_close', FALSE);
                }

                $sess_data = array(
                'username' => $username,
                'password' => $userpass
                );
                $this->session->set_userdata('logged_in', $sess_data);

                return 'authenticated';
            }
            else
            {
                return 'incorrect_password';
            }
        }
        else
        {
            return 'not_activated';
        }
    }
    else
    {
        return 'incorrect_username';
    }
}

public function email_exists($email)
{
    $sql = "SELECT name , email FROM users WHERE email = '{$email}' LIMIT 1";
    $result = $this->db->query($sql);
    $row = $result->row();

    return ($result->num_rows() === 1 && $row->email) ? $row->name : false;
}

public function verify_reset_password_code($email, $code)
{
    $sql = "SELECT name, email FROM users WHERE email = '{$email}' LIMIT 1";
    $result = $this->db->query($sql);
    $row = $result->row();

    if ($result->num_rows() === 1) 
    {
        return ($code == md5($this->config->item('salt').$row->name)) ? true : false;
    }
    else
        return false;
}


public function update_password()
{
    $email = $this->input->post('email');
    echo $this->input->post('password')."<br>";
    $password = sha1($this->config->item('salt').$this->input->post('new-password'));

    echo $this->input->post('password')." hashed password <br>";

    $sql = "UPDATE users SET password = '{$password}' WHERE email = '{$email}' LIMIT 1";
    $this->db->query($sql);

    if (isset($sql)) {
            return true;
        }   
        else
        {
            return false;
        }
}

private function set_session($session_data)
{
    $sess_data = array(
        'id' => $session_data['id'],
        'name' => $session_data['name'],
        'username' => $session_data['username'],
        'email' => $session_data['email'],
        'logged_in' => 1 );

    $this->session->set_userdata($sess_data);
}

}
?>

I'm setting session only when user logs in, Second problem is that there are so many records generated from time to time in db when we visiting/revisiting page, how do we handle record in db how do we delete the record when user logs out ? It just unset the data on calling

$this->session->sess_destroy();

i have been searching on it from more than two days, if anyone can help i would be grateful. I had a moment when these setting/code worked spot on but i don't know what happened it all messed up. If any other file is required please tell me. Thanks in advance

Habib Rehman
  • 590
  • 3
  • 15
  • 36

1 Answers1

1

Garbage Collector

As mentioned in the (old) CodeIgniter docs, CI has his own Garbage Collector. This is still true for CI 3.x

The Session class has built-in garbage collection which clears out expired sessions so you do not need to write your own routine to do it.

As stated in the CI forum, the Garbage Collector uses session.gc_probability and session.gc_divisor values, provided by your php.ini, to invoke the cleanup process. (By default, there is a chance of 1% to clean up the old sessions when making a session request)


Config Values

Anyway, I'd suggest you to set sess_regenerate_destroy to FALSE (according to the newer CI docs)

Whether to destroy session data associated with the old session ID when auto-regenerating the session ID. When set to FALSE, the data will be later deleted by the garbage collector.


Destroy session on tab close

$config['sess_expire_on_close'] is not available anymore in CI 3.x

For detecting the browser or tab close by using JavaScript (but it is slightly unreliable) , take a look on this answer. The easiest way to make a session last until the browser is being closed is to set the session_expiration value to 0.

The number of seconds you would like the session to last. If you would like a non-expiring session (until browser is closed) set the value to zero: 0

Source

Community
  • 1
  • 1
manniL
  • 7,157
  • 7
  • 46
  • 72
  • is this function called inside "sess_destroy()" ? – Habib Rehman Apr 25 '16 at 09:29
  • and so by this we don't need to care about deleting it ? – Habib Rehman Apr 25 '16 at 09:33
  • Nope, `sess_destroy()` only calls [session_destroy()](https://github.com/bcit-ci/CodeIgniter/blob/b4d719dc7fb3b010b53c09e7e82f979abf731ff9/system/libraries/Session/Session.php) – manniL Apr 25 '16 at 09:33
  • @HabibRehman: CI has his own Garbage Collector, so yes, you don't need to care about this! (Quote: "The Session class has built-in garbage collection which clears out expired sessions so you do not need to write your own routine to do it.") – manniL Apr 25 '16 at 09:35
  • thanks @manniL what about the first problem, direct link is getting access to the account :( – Habib Rehman Apr 25 '16 at 09:36
  • 1
    @HabibRehman Check this answer for the first problem: http://stackoverflow.com/a/20806014/3975480 – manniL Apr 25 '16 at 09:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/110123/discussion-between-habib-rehman-and-mannil). – Habib Rehman Apr 25 '16 at 09:45
  • 1
    @manniL ellislab does not deal with codeigniter any more use links from here http://www.codeigniter.com/docs –  Apr 25 '16 at 09:58
  • @wolfgang1983 You are right, I almost forgot that. Fixed it. – manniL Apr 25 '16 at 10:01
  • For the first problem I have checked the solution and its not working, From the document's point of view, there is no difference between a page refresh and the window being closed: the document is unloaded in both cases. And it deletes the session even if page is refreshed – Habib Rehman Apr 25 '16 at 11:29
  • Have you changed the cfg values? – manniL Apr 25 '16 at 11:51
  • if you are talking about "$config['sess_regenerate_destroy'] = FALSE;" yes i have changed it to FALSE again – Habib Rehman Apr 25 '16 at 12:47
  • @HabibRehman Please seperate your questions and ask each one for itself. I said everything to your problem(s) above. – manniL Apr 25 '16 at 15:34
  • 1
    The question is about CodeIgniter 3, while this answer refers to version 2.x - it is completely irrelevant. – Narf Apr 26 '16 at 07:40
  • @Narf AFAIK there hasn't been a change on the garbage collection mechanism from 2.x to 3.x – manniL Apr 26 '16 at 07:42
  • 2
    @manniL One of the major changes between 2.x and 3.0 is a completely new Session library ... Not only is there are change in the GC mechanism, but other than the public method names, there's almost **nothing in common** between the two. And GC mechanics only answer half of the question anyway. – Narf Apr 26 '16 at 07:48
  • @Narf Alright, I'll elaborate my answer and do some researchs. Thanks alot – manniL Apr 26 '16 at 07:50
  • @manniL nope, it doesn't work by even doing "0" to "session_expiration", the only process i have found little helpful is doing it with JS. | I have been able to make a difference between close a tab and refresh a tab the problem lies in "not doing anything when tab reloaded" – Habib Rehman Apr 26 '16 at 12:50