Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Session destroy wont log out users
  • First off I don't use the auth package, here is the login method
    public function action_login() {
    
            $this->template->title = 'login';
            $this->template->content = View::factory('welcome/index');
    
            $data = null;
    
            if (Input::method() == 'POST') {
    
                if (!Security::check_token()) {
                    Session::set_flash('error', 'the form has expired please refresh the page and try again');
                    return false;
                }
                $val = Validation::factory('login');
    
                $val->add('email')->add_rule('valid_email')->add_rule('required')->add_rule('min_length', 3);
                $val->add('password')->add_rule('required')->add_rule('min_length', 8);
    
                if (Input::method() == 'POST' && $val->run()) {
    
                    $password = Input::post('password');
                    $email = Input::post('email');
    
                    $user = Model_User::find()
                            ->related('admin')
                            ->where('email', $email)
                            ->get_one();
    
                    if (!$user) {
                        Session::set_flash('error', 'invalid email / password combo');
                        return false;
                    }
    
                    $session = Session::create();
    
                    if ($user->login($password) == true) {
    
    
                        $session->set('user_id', $user->id);
                        $session->set('authenticated', true);
    
                        if ($user->timezone) {
                            $session->set('timezone', $user->timezone);
                        }
    
                        if ($user->admin) {
                            $session->set('admin', true);
                        }
    
                        Response::redirect('home');
                        return;
                    }
                } else {
                    $data['errors'] = $val->errors();
                    Session::set_flash('error', 'invalid email / password combo');
                    return false;
                }
            }
        }
    

    Basically I set a session user_id and a bool variable authenticated to true. I have a session controller that is the main template for all other controllers on the site and it checks for these variables in the before() method like so
    class Controller_Session extends Controller {
    
        public $template = 'maintemplate';
        public $auto_render = true;
        public $user_id;
        public $admin = false;
    
        // Load the template and create the $this->template object
        public function before($data = null) {
    
            $session = Session::instance();
    
            if ($session->get('authenticated') == false || $session->get('user_id') == null) {
    
                Response::redirect('welcome/index');
                return true;
            }
    
            $this->user_id = $session->get('user_id');
    
            if ($session->get('admin') == true) {
                $this->admin = true;
            }
    }
    

    Now to log them out I thought i'd be able to just call Session::destroy() but it doesn't remove the set variables so I just get bounced back to the home page, the workaround that I do is manually set the variables to null like this
     public function action_logout() {
    
            $session = Session::instance();
    
            $session->set('authenticated', false);
            $session->set('admin', null);
            $session->set('user_id', null);
    
    
            Response::redirect('welcome/index');
            return true;
        }
    

    which works, but I dont get why session::destroy() doesn't.... well destroy all the session data. Also on a sorta related note is there any difference between getting the instance and setting it rather than directly calling Session::set('blah','value') ?
  • Just checked the session drivers, and ALL of them delete all data when you do a destroy:
    // reset the stored session data
    $this->keys = $this->flash = $this->data = array();
    
    The static methods all use "Session::instance()", the default session. Which should be the same as calling a dynamic method on the default instance. If you are using static calls everywhere, why not use Session::destroy() in your logout method? And check if you have auto_initialize on in your config. If so, you don't need to create a session, it will be created automatically when you load the Session class. In this case, a manual create just creates a new session (which for example in case of the db driver, doubles the number of session records!).
  • I changed all session getters/setters to static calls and its the same. This is probably a better method
    public function action_logout() {
    
            Session::delete('authenticated');
            Session::delete('admin');
            Session::delete('user_id');
    
            Response::redirect('welcome/index');
            
            return true;
        }
    

    But still if I throw in Session::destroy() call , those variables seem to come back some how and I'll get bounced back to the session controller like the user is still logged in. I don't really get whats going on. The above works fine, I just don't understand why Session::destroy() isn't destroying the variables.
  • Brian Perin wrote on Friday 21st of October 2011:
    I changed all session getters/setters to static calls and its the same. This is probably a better method
    public function action_logout() {
    
            Session::delete('authenticated');
            Session::delete('admin');
            Session::delete('user_id');
    
            Response::redirect('welcome/index');
            
            return true;
        }
    

    But still if I throw in Session::destroy() call , those variables seem to come back some how and I'll get bounced back to the session controller like the user is still logged in. I don't really get whats going on. The above works fine, I just don't understand why Session::destroy() isn't destroying the variables.

    It sounds like maybe those variables are being set again or something... What happens if you do a \Debug::dump(Session::get('authenticated'); immediately after you call Session::destroy()?
  • Does it work if you remove the redirect? Which browser are you using? IE for example has the habbit of cancelling all header processing when it sees a header redirect, which means cookie updates don't work (depending on the order in the header). Wether or not this is an issue also depends on the session driver used. All drivers using backend storage (file, db, memcached, etc) do a delete of that storage when you destroy the session. That means that even if the cookie isn't erased properly, the next page request will find the session missing and will create a new one. If you use cookie based sessions, all session data is stored in the cookie as well. If that cookie is not erased, you will still have the session after the redirect (as destroy only deletes the cookie). As good practice, try to avoid using cookie based sessions. The are very limited in storage, cause large headers due to sending all this data back and forth with every request, and you store potentionally sensitive data client-side, which from a security point of view isn't a good idea. File based sessions is a good alternative if you don't want them in the database.
  • Session::set()
    
    will use the default session instance, whereas if you use
    $session = Session::instance('blah');
    
    it will grab the 'blah' session instance, which can be completely different. Is there a particular reason you aren't using the Auth package? It's extremely flexible.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion