I'm having problems with session management (using cookies)
this is what happens...
1. no cookies are set, it makes you go to login
2. you log in, it verifies you, takes you to where you were previously
3. That page verified the cookies, and likes what it sees, extends the cookies
4. I hit enter on the url to go there again, and it creates the duplicate cookies with dummy values.
also, what happens sometimes is..it creates these cookies that should be created. They have the same name as the cookies that should be but the value is 1218648895 or some number like that and they expire at end of session (my cookies are all set for 1 hour)
heres the code
login class
PHP Code:
<?php
class Login
{
const cookie_session_field = 'sessionId';
const cookie_user_field = 'user';
const ERROR_EMPTY_LOGIN = 'Empty fields';
private $table_users = 'users';
private $column_password = 'password';
private $column_username = 'username';
private $column_ip = 'ip';
private $column_sessionID = 'sessionID';
private $encryption_method = 'SHA512';
private $salt = '';
private $session_id;
private $username;
private $password;
public function __construct()
{
}
public function destroyCookies()
{
setcookie(Login::cookie_user_field, time()-3600);
setcookie(Login::cookie_session_field, time()-3600);
}
public function getIP()
{
return $_SERVER['REMOTE_ADDR'];
}
//When a user is loggin in, this function is called, and they are verified as a legitimate user or not
public function verifyLogin($username, $password, $redirect)
{
// sets the classes private variables username and password to the escaped string version
$this->username = $this->clean($username);
$this->password = $this->encrypt($this->clean($this->salt . $password));
// checks to see if any fields were empty
if(empty($username) || empty($password))
{
$this->reLogin($redirect);
//throw new Exception(Login::ERROR_EMPTY_LOGIN);
}
else
{
$select = sprintf("SELECT * FROM %s WHERE %s = '%s' AND %s = '%s'",
$this->table_users,
$this->column_password,
$this->password,
$this->column_username,
$this->username);
$query = mysql_query($select);
if(mysql_num_rows($query) == 1)
{
//sets private variable $session_id to a random session ID
$this->session_id = $this->createSessionId();
// creates the cookies for the username and the session id
$this->createCookies($this->username);
$ip = $this->getIP();
// updates the table with the users sessionid, and current ip so we know the session hasn't been hijacked
$update = sprintf("UPDATE %s SET %s = '%s', %s = '%s' WHERE %s = '%s'",
$this->table_users,
$this->column_ip,
$this->getIP(),
$this->column_sessionID,
$this->session_id,
$this->column_username,
$this->username);
mysql_query($update);
header("Location:.." . $redirect);
}
else
{
$this->reLogin($redirect);
}
}
}
// after the user is validated, we set 2 cookies, the username, and session id
public function createCookies($username)
{
setcookie(Login::cookie_user_field, $username, time()+3600);
setcookie(Login::cookie_session_field, $this->session_id, time()+3600);
}
public function clean($dirty)
{
return mysql_real_escape_string($dirty);
}
//returns the input ($decrypted) into the decrytption algorithm defiend in the private variables
public function encrypt($decrypted)
{
return hash($this->encryption_method, $decrypted);
}
//this function creates a random string of the specified length so we can create a session id
//Using a session id so we don't have to store the password hash as a cookie
public function createSessionId()
{
$string_length = 30;
$chars = "abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
srand((double)microtime()*1000000);
$i = 1;
$pass = '';
while ($i <= $string_length) {
$num = rand() % 61;
$tmp = substr($chars, $num, 1);
$pass = $pass . $tmp;
$i++;
}
return hash($this->encryption_method, $pass);
}
public function reLogin($redirect)
{
header("Location:./login.php?url=" . $redirect);
}
protected function getVariable($var)
{
return $this->$var;
}
protected function setVariable($var, $set)
{
$this->$var = $set;
}
}
?>
session class (extends login)
PHP Code:
<?php
require_once('./classes/class.login.php');
class Session extends Login
{
/*
GETVARIABLE TYPES and set variable types
column_password
column_username
column_ip
column_sessionID
encryption_method
salt
session_id
username
password
*/
public function __construct()
{
$this->setVariable(username, $this->clean($_COOKIE[Session::cookie_user_field]));
if($this->getVariable(username) != NULL)
{
$this->checkSession();
}
else
{
$this->reLogin($this->getURL());
}
}
public function checkSession()
{
$this->setVariable(session_id,$this->clean($_COOKIE[Session::cookie_session_field]));
// sets up select statement inside teh query
$select = sprintf("SELECT %s, %s FROM %s WHERE %s = '%s' AND %s = '%s'",
$this->getVariable(column_sessionID),
$this->getVariable(column_ip),
$this->getVariable(table_users),
$this->getVariable(column_username),
$this->getVariable(username),
$this->getVariable(column_ip),
$this->getIP());
// end select statement
$query = mysql_query($select);
$user = mysql_fetch_array($query) or die(mysql_error());
if($user[$this->getVariable(column_sessionID)] == $_COOKIE[Session::cookie_session_field])
{
$this->extendCookies($this->username, $this->session_id);
}
else
{
$this->destroyCookies();
$this->reLogin($this->getURL());
}
}
public function getURL()
{
return $_SERVER['PHP_SELF'];
}
public function clean($dirty)
{
return mysql_real_escape_string($dirty);
}
//if the cookies are valid for the user, then
public function extendCookies($username, $sessionId)
{
setcookie(Session::cookie_user_field, $username, time()+3600);
setcookie(Session::cookie_session_field, $sessionId, time()+3600);
}
public function destroyCookies()
{
setcookie(Session::cookie_user_field, time()-3600);
setcookie(Session::cookie_session_field, time()-3600);
}
public function getIP()
{
return $_SERVER['REMOTE_ADDR'];
}
}
?>
and...starting it all
PHP Code:
require_once('./classes/class.session.php');
$session = new Session();