<

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x

Use sessions to register and track users

Published on
8,010 Points
1,910 Views
1 Endorsement
Last Modified:
Approved
Chris Gralike
Not too political, always looking for the best advice or solution, and if need be using a pragmatic approach.
In effect this is a session handler that registers sessions inside a database and verifies them based on a timestamp (session timeout). This code is just an skeleton that needs to be extended and altered to your own needs.

Installing is done in two steps.
First, create this table inside your mysql server.

Next create a new PHP file including the attached code snippet.
 
<?php 
class Sessions{
	private $id;			#Will contain the session ID generated from the inser ID in the database
	private $CTS;			#Holds the "Current Timeout"
	private $dbname;		#Database name that contains the session table
	private $dbhost;		#Database host that contains the deatabase containing the session table
	private $dbuser;		#Database user used to connect to the database.
	private $dbpass;		#Database Password used to connect to the database, assuming that one is always used.
	private $dblink;		#Strict var used to hold the link identifier created on database connect.
	private $timeout; 
	public function __construct($dbuser, $dbpass, $dbhost, $dbname, $session_timeout=''){
		if(!empty($dbuser) && !empty($dbpass) && !empty($dbhost) && !empty($dbname)){
			$this->dbuser = $dbuser;
			$this->dbpass = $dbpass; #assuming we always use a password
			$this->dbhost = $dbhost;
			$this->dbname = $dbname;
		}
		
		// Define a timeout.
		$this->timeout = (!empty($session_timeout)) ? $session_timeout : "5";
		
		// Start our session //
		session_start();
		
		// We redirect on error, so this is to prevent a redirect loop... //
		if(!isset($_SESSION['failcount'])){
			$_SESSION['failcount'] = 0;
		}
		
		// this is our error handler :P !//
		if(isset($_SESSION['failcount'])){
			if($_SESSION['failcount'] > 10){
				$err = '';
				if(@is_array($_SESSION['errors'])){
					foreach($_SESSION['errors'] as $key => $value){
						$err .= "$key => $value<br/>";
					}
				}else{
					$err = 'unknown error!';
				}
				die('Failed 10x to setup a decent session<br/>The following errors where reported!<br/>'.$err);
			}
		}
		
		// Create the current timestamp to work with // 
		$this->CTS = ((date('d')*3600)+(date('g') * 60)+date('i'));
		
		// Create a db connection to test connectivity//
		if(!$this->dbConnect()){ 
			$_SESSION['errors']['dbconnect'] = 'failed to connect to DB';
			// Unset the session active var //
			unset($_SESSION['active']);
			// Register the fact this happend // 
			$_SESSION['failcount']++;
			header('location:'.$_SESSION['location']);
		}
		
		// Cleanup old sessions (timed out sessions) //
		$this->CleanDb();
		
		// Validate this session //
		if(!isset($_SESSION['active'])){
			if($this->RegisterSession()){
				$this->dbClose();
				return true;
			}else{
				$this->dbClose();
				return false;
			}
		}else{
			$this->VerifySession();
			$this->dbClose();
		}
	}
    
	public function getOnline(){
		$this->dbConnect();
		if(is_resource($this->dblink)){
			$sql = 'SELECT DISTINCT COUNT(*) as online FROM session';
			$result = mysql_query($sql);
			$row = mysql_fetch_array($result);
			$this->dbClose();
			if($row['online'] > 0){
				return $row['online'];
			}else{
				return 1;
			}
		}else{
			return false;
		}
	}
	
	// Get number of minutes online
	public function getBrowseTime(){
		return $_SESSION['ttime'];
	}
	
	public function getStartTime(){
		$secs = $_SESSION['btime'] * 60;
		$hours = round(($secs  / (60 * 60) %24));
		$min = round(($secs  / 60) %60);
		return $hours .":". $min;
	}
	
	public function whoami(){
		return $_SESSION['username'];
	}
	
	// Open a database connection.
	private function dbConnect(){
		if(!empty($this->dbuser) && !empty($this->dbpass) && !empty($this->dbhost)){
			if(@$this->dblink = mysql_connect($this->dbhost, $this->dbuser, $this->dbpass)){
				if(@mysql_select_db($this->dbname, $this->dblink)){
					return $this->dblink;
				}else{
					$_SESSION['errors']['database'] = 'no valid database could be selected';
				}
			}else{
				$_SESSION['errors']['database'] = 'Connection with database failed';
			}
		}else{
			$_SESSION['errors']['database'] = 'Not all required db connection info was available';
		}
		return false;
	}
	
	private function dbClose(){
		if(is_resource($this->dblink)){
			mysql_close($this->dblink);
		}
	}
	
	// Clean up all timed out session registrations.
	private function CleanDb(){
		if(is_resource($this->dblink)){
			$sql = 'select * from session';
			$result = mysql_query($sql, $this->dblink);
			while($row = mysql_fetch_array($result)){
				$tdiff = $this->CTS - $row['sess_ltime'];
				if($tdiff >= $this->timeout){
					$delete = 'DELETE FROM session where sess_id = "'.$row['sess_id'].'"';
					mysql_query($delete);
				}
			}
		}else{
			$_SESSION['errors']['dbclean'] = 'No db link resource for cleanup';
		}
	
	}
	// Method to handle registrations // 
	private function RegisterSession(){
		// Hold all the session information available inside the _Session var.
		$_SESSION['active']    = true;
		$_SESSION['name']      = session_name();
		$_SESSION['btime']     = $this->CTS;
		$_SESSION['ltime']     = $this->CTS;
		$_SESSION['ttime']     = '1';
		$_SESSION['username']  = 'guest';
		$_SESSION['location']  = $_SERVER['REQUEST_URI'];
		
		if(is_resource($this->dblink)){
			$sql = 'INSERT INTO session(sess_name, sess_btime, sess_ltime, sess_ttime, sess_username, sess_location)
			        VALUES("'.$_SESSION['name'].'","'.$_SESSION['btime'].'","'.$_SESSION['ltime'].'",
					       "'.$_SESSION['ttime'].'","'.$_SESSION['username'].'","'.$_SESSION['location'].'")';
			if(mysql_query($sql, $this->dblink)){
				$_SESSION['id'] = mysql_insert_id();
				// If we had any failures we reset them here //
				$_SESSION['failcount'] = 0;
				return true;
			}else{
				$_SESSION['errors']['register'] = 'failed to register session inside the database, online info might not be available';
				// Unset the session active var //
				unset($_SESSION['active']);
				// Register the fact this happend // 
				$_SESSION['failcount']++;
				header('location:'.$_SESSION['location']);
			}
		}else{
			$_SESSION['errors']['register'] = 'unable to register session, no database link available';
			// Unset the session active var //
			unset($_SESSION['active']);
			// Register the fact this happend // 
			$_SESSION['failcount']++;
			header('location:'.$_SESSION['location']);
		}
	
	}
	
	private function VerifySession(){
		if(isset($_SESSION['active'])){
			if(is_resource($this->dblink)){
				$sql = 'SELECT * from session where sess_id = "'.$_SESSION['id'].'"';
				if($result = mysql_query($sql)){
					$row = mysql_fetch_array($result);
					if(isset($row['sess_id'])){
						//Verify the times again for a timeout //
						$tdiff = $this->CTS - $row['sess_ltime'];
						if($tdiff >= $this->timeout){
							// If the session timedout//
							// Delete the session from the database //
							$delete = 'DELETE FROM session where sess_id = "'.$row['sess_id'].'"';
							mysql_query($delete);
							// Unset the session active var //
							unset($_SESSION['active']);
							// Register the fact this happend // 
							$_SESSION['failcount']++;
							header('location:'.$_SESSION['location']);
						}else{
							// Hold all the session information available inside the _Session var.
							$_SESSION['ttime'] = $this->CTS - $row['sess_btime'];
							$_SESSION['ltime'] = $this->CTS;
							$_SESSION['location']  = $_SERVER['REQUEST_URI'];	
							// We need to update the fact we had activity ;-) //
							
							$update = 'UPDATE session SET sess_ltime="'.$this->CTS.'", sess_ttime="'.$_SESSION['ttime'].'", sess_location="'.$_SESSION['location'].'"
							           WHERE sess_id = "'.$_SESSION['id'].'"';
							mysql_query($update);
							return true;
						}
					}else{
						// Session was allready delete from database. Other users browsing maybe? :)
						// Handle it like a timedout session.
						unset($_SESSION['active']);
						// Register the fact this happend.
						$_SESSION['failcount']++;
						header('location:'.$_SESSION['location']);
					}
				}else{
					// The query failed for unkown reasons//
					unset($_SESSION['active']);
					// Register the fact this happend. 
					$_SESSION['failcount']++;
					header('location:'.$_SESSION['location']);
				}
			
			}else{
				$_SESSION['errors']['verify'] = 'No dblink available for verification';
				unset($_SESSION['active']);
				return false;
			}
		}else{
			die('H4(k 4t73mpt!');
		}
	}
}

Open in new window


For example you created a file called "session.class.php" that contains the code, you then need to upload that file to your webserver.

Next you need to guarantee that this file is loaded and initialized each time a user browses to a new location, usually this is done by including this file and initialization code to the header of your page(s).

Including the file works like this;
 
<?php
$PHPEx='.php';
include('session.class'.$PHPEx);
?>

Open in new window


When this is done you need to initialize the class after which you are able to access it using the following directives;
 
<?php
$session = new Sessions('dbuser', 'dbpass', 'dbhost', 'dbname', 'timeout in min');
echo "There are:".$session->getOnline()." users online.<br />";
echo "You started browsing at :".$session->getStartTime()."u<br />";
echo "Our current time is ".date('h:i')."u <br />";
echo "You have been active for :".$session->getBrowseTime()."Mins.<br />";
echo "You are known as :".$session->whoami()."<br />";
?>

Open in new window


You can also add all the snippets inside one file and include that in your application.

Again, this class still needs allot of work if you want it to maintain "loggedin" users and related sessions. In this stage the "how many users are online" can be queried and own session information like how long have iv been browsing.

Good luck on extending this class.

Rgrds, Chris
1
Comment
1 Comment
LVL 11

Author Comment

by:Chris Gralike
If you get this error :

Failed 10x to setup a decent session
The following errors where reported!
database => Connection with database failed
dbconnect => failed to connect to DB
dbclean => No db link resource for cleanup
register => unable to register session, no database link available

Then check your database connection information. For the everyone that dont read code comments, this class "ONLY" accepts database login "USING PASSWORD". The blanks are not accounted for in the code.

Good luck and rgrds,
0

Featured Post

OWASP Proactive Controls

Learn the most important control and control categories that every architect and developer should include in their projects.

Join & Write a Comment

The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month