views:

321

answers:

3

Hi everyone, i think my problem is a little weird, ive wrote a little class to log in/out user, entire system is based in MVC pattern, and my libraries are custom and self written, but the problem: when i log in the user with out the $remember flag, no problems, sessions are easily set and unset. but when i activate the $remember and i create a cookie, my logout function does not work, it deletes the session but not the cookie, so cookie remains in browser with complete data, and whenever i reload the page , my class logs me in again because there is a cookie with full authentication details, the problem is with a cookie, i cant send other headers like Location: blah blah from $this->logout; ive tried different ways to unset cookie, but no luck; this is the class:

<?php
/**
 * Pars----
 * Classified --- Application
 *
 * @author Sallar Kaboli ([email protected])
 * @copyright Copyright (C) 2009 - 2010 -----CO ([email protected])
 * @package Pars---
 * @version 1.0
 */

class ParsUser {

    public $userID = false;

    private $_p = null;
    public $userData = null;

    public function __construct() {
        $this->_p = ParsRegistry::getInstance();
        if( $this->_p->sess->isVarSet('parsUser') ) {
            $this->loadUser($this->_p->sess->getVar('parsUser'));
        }

        if( isset($_COOKIE['parsUser']) and !$this->isLoggedIn() ) {
            $userFromCookie = unserialize(base64_decode($_COOKIE['parsUser']));
            $this->checkLogin($userFromCookie['username'], $userFromCookie['password'], true, false);
        }
    }

    public function checkLogin($username, $password, $remember = true, $hash = true) {

        if(!empty($username) and !empty($password)) {

            $password = $hash ? $this->_p->valid->hash($password) : $password;
            $qData = array('user' => $username, 'pass' => $password);
            $query = 'SELECT * FROM people WHERE `username` = :user AND `password` = :pass';

            $user = $this->_p->db->getRow($query, $qData);

            if(is_object($user) AND !empty($user->id)) {

                $this->userID = $user->id;
                $this->userData = $user;

                if( $hash ) {
                    $this->_p->db->execute('UPDATE people SET `last_login` = ? WHERE `id` = ?', array( time(), $this->userID ));
                }

                $this->loginTheUser($remember);
                return true;

            }
            else {
                return false;
            }
        }
        else {
            return false;
        }
    }

    private function loginTheUser($remember = true) {
        $this->_p->sess->setVar('parsUser', $this->userID);

        if( $remember ){
            $rememberPeriod = $this->_p->conf->c['cookie_remember_period'];
            $cookie = array(
                      'username' => $this->userData->username,
                      'password' => $this->userData->password
                      );

            $cookie = base64_encode(serialize($cookie));
            setcookie('parsUser', $cookie, time() + $rememberPeriod/*, '/', $_SERVER['HTTP_HOST']*/);
        }
        return false;
    }

    private function loadUser($userID){

        $user = $this->_p->db->getRow('SELECT * FROM people WHERE `id` = ?', $userID);

        if( is_object($user) and ( $user->id == $userID ) ){

            $this->userID = $user->id;
            $this->userData = $user;
            $this->_p->sess->setVar('parsUser', $this->userID);

            return true;
        }
        else return false;

    }

    public function logout($redirectTo = false) {
        setcookie('parsUser', '', mktime(12,0,0,1, 1, 1990));
        unset($_COOKIE['parsUser']);
        $this->_p->sess->sessionDrop();
        $this->userData = null;
        $this->userID = false;

        if ( !empty($redirectTo) ){
               $this->_p->core->redirect($redirectTo);
               exit;
            }
    }

    public function isLoggedIn() {
        //return ( empty($this->userID) OR !$this->userID ) ? false : true;

        if( $this->userID > 0 and $this->userID != false and !empty($this->userID) )
            return true;
        else return false;
    }

    public function checkAccess($level) {
        if($level == 0) {
            return true;
        }
        elseif($this->isLoggedIn()) {
            if( $this->userData->level <= $level ) {
                return true;
            }
            else {
                return false;
            }
        }
        else {
            return false;
        }
    }

    public function getUserData() {

        $args = func_get_args();

        if( empty($this->userID) )
           throw new Exception('User is not loaded.');

        if( is_array($args) and count($args) > 0){
            foreach( $args as $arg ){
                if( !isset($this->userData->$arg) )
                    throw new Exception('Unknown property: <b>' . $property . '</b>');
                else
                    $props[$arg] = $this->userData->$arg;
            }

            if( count($args) == 1 )
                return $props[$args[0]];
            else
                return $props;
        }
        else{
            $props = $this->userData;
            unset($props->password);
            return $props;
        }

    }


}

sorry for my english.

A: 

Sorry for my strange question but why do you set a cookie in history (so it's gets deleted) and then unset a cookie that doesn't exist anymore?

Hmm looks strange if you look at the output of your image... What is the system time of your server? Because it said the cookie would expire in 1990.. Looks like your computer/server is way behind if that is still valid :P

By the way, maybe you can't edit the data, because you need to decode the base64 encryption first (because in your code when you set it, you use the base64 function)

Bloeper
thats because setcookie() in history did not work, i tried to unset it, but i didnt work too.
Sallar Kaboli
A: 

You could set the cookie with invalid data:

setcookie('parsUser', 'trash', time() - 3600);

If this doesn't delete the cookie, it should at least create an invalid login token.

I would also recommend against base64 encoding the username and password in the cookie. It's all but plaintext to an experienced attacker. You can easily integrate strong encryption into your application using mcrypt:

http://us2.php.net/mcrypt

If that's not an option, you can use a php-only implementation of xor encrypt with strong keys. There are also php-only implementations of blowfish and Rijndael on the internet. I'd provide links if I could, but my current reputation won't let me add more than one hyperlink.

Luu
About the cookie, let me check it out.i agree about base64. it was just for a test. its not final class. thanks.
Sallar Kaboli
i just checked it out, i cant change the value of cookie either. @Gumbo: this is server response, when i call the logout method from my controller: as u see, server tries to change the value, but the cookie does not change. http://img3.tinypic.info/files/mo5mjgecac7ss2a18o0f.jpgtried to put an echo before setcookie to check if it runs or not, it does run, and server responses. but...
Sallar Kaboli
Tnx Luu, i managed to implement Rijndael with mcrypt, its perfect. thanks again.
Sallar Kaboli
A: 

try to set $path in both cases (create, remove cookie)

Dmitry Merkushin
Sallar Kaboli

related questions