Jump to content

Archived

This topic is now archived and is closed to further replies.

master82

Cookie Vs Sessions

Recommended Posts

Ok i'm about to create a login form simply asking for a username and password. I know that cookies and sessions are very similar but I was wondering which was better for me.

Once they have logged in they will have access to all of the site, however each page has information specific to the user, and that user only. so I need the session/cookie to store a few values that I can retrieve at the top of the php script (ie the users id) so that I can simply take that value from the cookie/session and use it to display the users info

(ie SELECT * FROM table WHERE userid=[id from cookie/session]

Firstly, can this be done?
Which one is better for this, and
is this a secure way to retrieve the users information?

NB - users not logged in with cookie/session I can redirect those to login page so there is some security there (i think lol)

Share this post


Link to post
Share on other sites
<getting on soapbox>
Personally, I hate cookies. Period. I'd turn them off, but I'd loose too much connectivity. I think it contermands everything we are striving for: Secure Client Machines... Blah Blah Blah...

</getting on soapbox>

Ok,

Sessions have been my approach to this problem, and I like them...

I think it's really a preference thing more than a security thing, for the most part...

Share this post


Link to post
Share on other sites
IF your are planning on storing things such as usernames and passwords in a session or cookie. Then I'd choose sessions as . the client wont be able to get the session data as it is stored on the server rather than the clients computer
2. its more secure than cookies

As cookies are set on the users computer and so they can be easily accessed.

I will only use cookies for things like, tracking how many times a user has visited a page, or where the user has last been for redirectional purposes etc. I will not store personal info in a cookie and opt for sessions.

Share this post


Link to post
Share on other sites
I take things a step further and I don't even use sessions to store my data. I use a mysql table called sessions. In this table I store the id of the row in the users table where all the user's information is stored and the sid (session ID) so I can keep track of the user. I created a simple script to remove sessions when the user logs out or by expiration if the user does not do anything for x number of seconds on the site they are logged out. I also store their IP address and could have a user logged out if they tried to access the site from a different computer forcing an active sid for someone else. Additionally I can track users/guests that are currently logged in via the sessions table. This opens up many avenues for additional features. If you would like to know my about how it all works and why I did it the way that I did, then let me know and I would be happy to share my code snippets and an explanation of them.

Share this post


Link to post
Share on other sites
That would be great - I'd like to know more about this session table and how it works.

I've still to create the login form and actions that will occompany it because I cannot seem to find any scripts that actually work (or are understandable to my begginers knowledge of PHP lol).

Will you be able to take me through step by step as to what you did?

Share this post


Link to post
Share on other sites
Certainly. I am headed out right now, but I will post the scripts and explain them for session management/user authentication. If I have not posted them by the end of the day you might want to PM me to remind me to do so.

Share this post


Link to post
Share on other sites
Okay so you want to manage session with a MySQL database so you can track users in real time, so we'll start with how to create sessions and a table for the sessions.

[code]<?php

session_start(); // We need the unique SID to create our sessions.

// Now we need a connection to the database.
// Fill in those values that match your database.

$link = mysql_connect('database host address', 'username', 'password') or die("MySQL: ".mysql_error());
mysql_select_db('database name', $link) or die("MySQL: ".mysql_error());

// Since this may be the first time running the script we need to make sure we have a sessions table.
// We will do it with a simple MySQL Query.  You can disect the following query to see how it works.

mysql_query("CREATE TABLE IF NOT EXISTS `sessions` (`id` int(11) NOT NULL auto_increment, `sid` text NOT NULL, `uid` int(11) NOT NULL, `ip` text NOT NULL, `timeout` int(11) NOT NULL default '0', PRIMARY KEY  (`id`))", $link);

// Now we will loop through the list of sessions and if there are any expired we will remove them.
// This is important so someone doesn't leave the site and leave a session open.

$result = mysql_query("SELECT * FROM sessions", $link);
while ($row=mysql_fetch_assoc($result)) {
  if ( $row['timeout'] <= time() ) {
    mysql_query("DELETE FROM sessions WHERE id=".$row['id']." LIMIT 1", $link);
  } elseif ( $row['sid'] == session_id() ) {
    mysql_query("UPDATE sessions SET timeout=".(time()+600)." WHERE sid='".session_id()."' LIMIT 1", $link);
    $session = mysql_fetch_assoc(mysql_query("SELECT * FROM sessions WHERE sid='".session_id()."' LIMIT 1", $link));
  }
}

// If you did not already have a session assigned to you create one now.

if ( !is_array($session) ) {
  mysql_query("INSERT INTO sessions values ('', '".session_id()."', '-1', '".$_SERVER['REMOTE_ADDR']."', ".(time()+600).")", $link);
  $session = mysql_fetch_assoc(mysql_query("SELECT * FROM sessions WHERE sid='".session_id()."' LIMIT 1", $link));
}

// Now if we have nothing left to do we can close our database connection.
// The $session array still holds your session info which can be used to verify that you are logged in still.

mysql_close($link);

?>[/code]

Place that at the top of each page to handle whether users are logged in or not and guest users, so you can monitor real time traffic.

Share this post


Link to post
Share on other sites
Now that you have your sessions table and your sessions up and running, you need a way for users to log in. You can use a form that gets submitted to a page to process the login or you could use the http authentication method. There is an example of this in the tutorials of this site and I would be happy to review the modifications to make this work with the snippets I am posting. Now this will be a page I will call login.php to process the login.

Additionally, I have written this to restrict accounts to only one login per username. If this is not something you are interested in I can point out the specific lines to change.

[code]<?php

$link = mysql_connect('database host address', 'username', 'password') or die("MySQL: ".mysql_error());
mysql_select_db('database name', $link) or die("MySQL: ".mysql_error());

if ( isset($_GET['logout']) ) {
  // We are logging out, but we want to maintain the session as a guest user.
  mysql_query("UPDATE sessions SET uid=-1 WHERE sid='".session_id()."' LIMIT 1", $link);
  mysql_query("UPDATE sessions SET timeout=".(time()+600)." WHERE sid='".session_id()."' LIMIT 1", $link);
  mysql_query("UPDATE sessions SET level='0' WHERE sid='".session_id()."' LIMIT 1", $link);  
  header("Location: index.php"); // We are done head back to the main page. (This could also go to the refering page.)
} else {
  // We are attempting to login now.
  $row = mysql_fetch_assoc(mysql_query("SELECT * FROM users WHERE name='".$_POST['username']."' LIMIT 1", $link));
  if ( mysql_num_rows(mysql_query("SELECT * FROM sessions WHERE uid=".$row['id']." LIMIT 1", $link)) != 1 ) {
    if ( $_POST['password'] == $row['pass'] ) {
      // Username/Password pair verified change the session from guest to admin or user as the case may be.
      mysql_query("UPDATE sessions SET uid=".$row['id']." WHERE sid='".session_id()."' LIMIT 1", $link);
      mysql_query("UPDATE sessions SET timeout=".(time()+600)." WHERE sid='".session_id()."' LIMIT 1", $link);
      header("Location: index.php"); // We are logged in head over to the main page.
    } else {
      echo "      <span class=\"error\">Invalid username/password.</span>\r\n";
    }
  } else {
    echo "      <span class=\"error\">User already logged in.</span>\r\n";
    echo "      <p>We do not allow multiple sessions for the same user. If this is your account this might mean that someone has gained access to your username and password without your consent. If this is the case, please contact an administrator about changing your password.</p>\r\n";
  }
}
mysql_close($link);

?>[/code]

Now this won't function without having a table full of users. That's our next step, to create our users table and put some users in it so they can access the site. For right now, I must go and get some sleep. This will give you a chance to review everything and ask questions on anything you do not understand. I might write an actual tutorial later which will break the code down and explain it step by step.

Share this post


Link to post
Share on other sites
OK I've gone through that and I'm quite happy with whats going on - your explinations within the code are very clear :)

One think I will ask is, with the first script you provided, it checked to see if a sessions table was present, if not it would create it. Now that it is created, can I now remove that part of the code or are values needed further down the script from this part - I suspect not but your the expert :)

Think I'm ready for the users table and whatever comes next...



NB - I think you should write a tutorial on this as your are very clear in your explinations!

Share this post


Link to post
Share on other sites
To answer your question, yes once you have created the table that line is no longer needed, but it doesn't hurt to leave it and if you were to use this script on a test server (like on your personal computer) and then move to another server you would need to create the tables again. If the table is already there the script does nothing but if it doesn't exist it creates it.

I've got to run again, but I will try to explain the users table with a simple registration script. That way you can start logging in and testing everything. Then we will cover user management. I believe the last thing we will need to cover is one of those live counters to tell you how many people are online. You can see an example at the bottom of this page.

Share this post


Link to post
Share on other sites
I am sorry I have not responded in so long, but I have been extremely busy the last few days. I will try to get the rest posted tomorrow morning. If not then, hopefully tomorrow evening. I have meeting with a client tomorrow afternoon.

Share this post


Link to post
Share on other sites
master82 is right it is explaind very weel i may try it my self since my sessions are keep giving me problems you said to post that code at the top of every page wouldn't it be easier to create a seperate page
like sessions.php and use the include function to place it on every page like this

include 'sessions.php';
or

include("sessions.php");

i think that would be better in the long run if you have to edit the other code on the page you wont have to look through all of this code to find what you want to edit thats just my personal opinion though but code is a great idea

Share this post


Link to post
Share on other sites
Yes, shortj, it is easier to include a separate page...you figured me out. :-D

I use header.php and footer.php on my pages to propigate my layout and the code that goes on every single page across my entire site. The portion of the code I said goes on every page is just a snippet from header.php.

I seem to have lost my mind...have any of you seen it? Things have been so crazy around here the last few days with upgrading systems and such. I was supposed to write a registration page, right? Was there something else besides that? I'll post tomorrow.

New System:
AMD64 Athlon 3200+ (2,000 Mhz)
512MB DDR
Western Digital 300GB 7200RPM 8MB Cache
nVidia 6600GT 128MB
SuSE Linux 10.0
ASUS A8V-E SE

Share this post


Link to post
Share on other sites
Yes - the registration page and a users table I think is all you said was now needed :)

Really thankful for your time, I know you seem extremly busy. Its not often you find a forum where people actually take the time to help people

Share this post


Link to post
Share on other sites
I do what I can, and incidently, yes I do stay very busy. Okay, so down to business...

You will need a table for all of your users and the information about each one you need to have access to for whatever reason. Let's just go over the basic layout of the table you'll need and then we can get down to the registration coding. You will have to excuse me because I formatted my box when I upgraded and I didn't keep my files on this topic, so everything is coming off the top of my head.

Well you will need a unique identifier that will auto_increment...we'll call this field id and it will be int(11). It will be the primary unique identifier. A username of course is a must so we'll call it name and make it a text field (you can specify a max size if you like). We can't let them login without a password so let's call this next one pass and make it text as well (you can use password type, but for the moment we won't get into any encryption). Now you may want your users to supply extra information like an e-mail address or something, but I leave that at your discretion. You now have the basics of this table setup and you can have registered users.

We have a table, but now we need a way to put the information in it...let's create separate pages for the moment so as not to get confused with too much code on one page. First we need a registration form to write information to the users table.

[code]<form action="doreg.php" method="POST">
  <label for="username">Username:</label> <input type="text" name="username" id="username" /><br />
  <label for="password">Password:</label> <input type="password" name="password" id="password" /><br />
  <label for="confirmpass">Confirm Password:</label> <input type="password" name="confirmpass" id="confirmpass" /><br />
  <input type="submit" value="Register" />
</form>[/code]

I put two password fields so you can make sure they typed the same thing twice. You don't have to do this and can leave the confirmation code out of the doreg.php page. The <label></label> is just for standard compliance and for people who use screen readers and such to help them navigate the site better.

Now for the fun part. Let's do something with the username and password they just gave us.

[code]<?php

// Need to create a connection to the database again
$conn = mysql_connect([db host], [username], [password]) or die(mysql_error());
mysql_select_db([db name], $conn) or die(mysql_error());

// Let's setup an empty variable to hold our error messages.
$error = "";

// Let's make sure that they typed the same password twice
if ( $_POST['password'] != $_POST['confirmpass'] ) $error .= "Your passwords did not match.<br />\r\n";

// Now let's see if there were anymore problems like empty fields.
if ( $_POST['username'] == "" ) $error .= "You must enter a username.<br />\r\n";
if ( $_POST['password'] == "" ) $error .= "You must enter a password.<br />\r\n";

//Now we must make sure no one else is using that username
if (mysql_num_rows(mysql_query("SELECT name FROM users WHERE name='".$_POST['username']."' LIMIT 1", $conn)) == 1) $error .= "Username already taken.<br />\r\n";

// Okay let's make sure we didn't have any errors or if we did then tell the people what went wrong.
if ( $error != "" ) die($error);

// Well since none of the errors we accounted for occured let's create a new entry in the database for our user.
if (mysql_query("INSERT INTO users values ('', '".$_POST['username']."', '".$_POST['password']."')", $conn)) {
  header('Location: index.php'); // You successfully registered the user now let's send them back to the main page.  Alternatively you could just echo a message here saying something like "Success! You have been registered click [here] to go to the login page.
} else {
  die(mysql_error()); // Something went wrong with the registration.
}

?>[/code]

I think that pretty much covers everything. If you have any questions or if you feel I skipped something you really needed, then just let me know. Alternatively if anyone has any better ideas on this matter or if you see a mistake in my coding, I would really like to know.

Otherwise have fun and happy coding!

Share this post


Link to post
Share on other sites
Thanks for that :)

I did come across 2 errors, the first was your form (two actions, instead of a 'method' and 'action')

The second is something to do with the doreg.php on line 18

[code]
if (mysql_result(mysql_query("SELECT username FROM users WHERE username='".$_POST['username']."' LIMIT 1", $conn), 0)) $error .= "Username already taken.<br />\r\n";
[/code]

I get the following output in my browser:

Warning: mysql_result() [function.mysql-result]: Unable to jump to row 0 on MySQL result index 3 in D:\Xampp\xampp\htdocs\Sessiontutorial\doreg.php on line 18

Warning: Cannot modify header information - headers already sent by (output started at D:\Xampp\xampp\htdocs\Sessiontutorial\doreg.php:18) in D:\Xampp\xampp\htdocs\Sessiontutorial\doreg.php on line 25


However, ofter checking the database, the new records have been inserted.

Any ideas what the problems is?

Share this post


Link to post
Share on other sites
[!--quoteo(post=354800:date=Mar 14 2006, 09:14 AM:name=txmedic03)--][div class=\'quotetop\']QUOTE(txmedic03 @ Mar 14 2006, 09:14 AM) [snapback]354800[/snapback][/div][div class=\'quotemain\'][!--quotec--]
Now that you have your sessions table and your sessions up and running, you need a way for users to log in. You can use a form that gets submitted to a page to process the login or you could use the http authentication method. There is an example of this in the tutorials of this site and I would be happy to review the modifications to make this work with the snippets I am posting. Now this will be a page I will call login.php to process the login.

Additionally, I have written this to restrict accounts to only one login per username. If this is not something you are interested in I can point out the specific lines to change.

[code]<?php

$link = mysql_connect('database host address', 'username', 'password') or die("MySQL: ".mysql_error());
mysql_select_db('database name', $link) or die("MySQL: ".mysql_error());

if ( isset($_GET['logout']) ) {
  // We are logging out, but we want to maintain the session as a guest user.
  mysql_query("UPDATE sessions SET uid=-1 WHERE sid='".session_id()."' LIMIT 1", $link);
  mysql_query("UPDATE sessions SET timeout=".(time()+600)." WHERE sid='".session_id()."' LIMIT 1", $link);
  mysql_query("UPDATE sessions SET level='0' WHERE sid='".session_id()."' LIMIT 1", $link);  
  header("Location: index.php"); // We are done head back to the main page. (This could also go to the refering page.)
} else {
  // We are attempting to login now.
  $row = mysql_fetch_assoc(mysql_query("SELECT * FROM users WHERE name='".$_POST['username']."' LIMIT 1", $link));
  if ( mysql_num_rows(mysql_query("SELECT * FROM sessions WHERE uid=".$row['id']." LIMIT 1", $link)) != 1 ) {
    if ( $_POST['password'] == $row['pass'] ) {
      // Username/Password pair verified change the session from guest to admin or user as the case may be.
      mysql_query("UPDATE sessions SET uid=".$row['id']." WHERE sid='".session_id()."' LIMIT 1", $link);
      mysql_query("UPDATE sessions SET timeout=".(time()+600)." WHERE sid='".session_id()."' LIMIT 1", $link);
      header("Location: index.php"); // We are logged in head over to the main page.
    } else {
      echo "      <span class=\"error\">Invalid username/password.</span>\r\n";
    }
  } else {
    echo "      <span class=\"error\">User already logged in.</span>\r\n";
    echo "      <p>We do not allow multiple sessions for the same user. If this is your account this might mean that someone has gained access to your username and password without your consent. If this is the case, please contact an administrator about changing your password.</p>\r\n";
  }
}
mysql_close($link);

?>[/code]

Now this won't function without having a table full of users. That's our next step, to create our users table and put some users in it so they can access the site. For right now, I must go and get some sleep. This will give you a chance to review everything and ask questions on anything you do not understand. I might write an actual tutorial later which will break the code down and explain it step by step.
[/quote]

This may sound like a stupid question but i'm going to ask it anyway. I have created this login page and added a form at the bottom where users can enter username and password. However, do i also require the session start script that creates the session table at the top of this login.php page? The reason i ask is surely this part of the code will always return nothing because the session table hasn't been created yet.

[code]
if ( mysql_num_rows(mysql_query("SELECT * FROM sessions WHERE uid=".$row['id']." LIMIT 1", $link)) != 1 ) {
[/code]

The login.php page is always going to be the first page called. How can you select all from session when session doesn't exist? Also session won't exist until someone logs in. When i try to run my login.php script with the code contained above i get a warning:mysql_num_rows():supplied argument is not a valid MySQL result resource on the line shown above. Can someone perhaps explain what code needs to be in my login page?

Share this post


Link to post
Share on other sites
The sessions table has three user levels admin, user and guest (on my particular setup anyway). When someone visits the page it creates a "guest" session for the live counter to use. Since I wrote this to be integrated with a live counter, you would need to make some modifications so you do not need the session_start on the login page.

It seems that you found something I overlooked when I wrote this code. When the user does not previously exist it returns an invalid query result. I have made the needed changes in my earlier post to fix the code. I look forward to any more questions or comments you may have.

[code]if (mysql_num_rows(mysql_query("SELECT username FROM users WHERE username='".$_POST['username']."' LIMIT 1", $conn)) == 1) $error .= "Username already taken.<br />\r\n";[/code]

Share this post


Link to post
Share on other sites
I've tried to run these scripts without success. Now i've no doubt the error is on my part and not yours. My login.php page constantly gave me the invalid query result and header problems. So i got a bit adventurous and decided to mix and match your login script with the script you suggested we put at the top of every page. My login.php now looks like the following:

[code]
<?php
if(isset($_POST['submit'])){
session_start();
$link = mysql_connect('localhost', 'root', '********') or die("MySQL: ".mysql_error());
mysql_select_db('project', $link) or die("MySQL: ".mysql_error());

// Since this may be the first time running the script we need to make sure we have a sessions table.
// We will do it with a simple MySQL Query.  You can disect the following query to see how it works.

mysql_query("CREATE TABLE IF NOT EXISTS `sessions` (`id` int(11) NOT NULL auto_increment,`uid` int(11) NOT NULL, `timeout` int(11) NOT NULL default '0', PRIMARY KEY  (`id`))", $link);

// We are attempting to login now.
  $row = mysql_fetch_assoc(mysql_query("SELECT * FROM users WHERE email='".$_POST['Login_email']."' LIMIT 1", $link));
  if(mysql_num_rows(mysql_query("SELECT * FROM sessions WHERE uid=".$row['user_id']." LIMIT 1", $link)) != 1 ) {
    if ( $_POST['Password'] == $row['password'] ) {
      // Username/Password pair verified change the session from guest to admin or user as the case may be.

      // If you did not already have a session assigned to you create one now.

      if (!is_array($session) ) {
        mysql_query("INSERT INTO sessions (uid, timeout) values ('".$row['user_id']."', ".(time()+600).")", $link);
        $session = mysql_fetch_assoc(mysql_query("SELECT * FROM sessions WHERE sid='".session_id()."' LIMIT 1", $link));
      }

      mysql_query("UPDATE sessions SET uid=".$row['user_id']." WHERE sid='".session_id()."' LIMIT 1", $link);
      mysql_query("UPDATE sessions SET timeout=".(time()+600)." WHERE sid='".session_id()."' LIMIT 1", $link);
      header("Location: logged_in2.php"); // We are logged in head over to the main page.
    } else {
      echo "<span class=\"error\">Invalid username/password.</span>\r\n";
    }
  } else {
    echo "<span class=\"error\">User already logged in.</span>\r\n";
    echo "<p>We do not allow multiple sessions for the same user. If this is your account this might mean that someone has gained access to your username and password without your consent. If this is the case, please contact an administrator about changing your password.</p>\r\n";
  }

mysql_close($link);
}else{

?>
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

    <head>
    <meta http-equiv="content-type"content="text/html;charset=encoding"/>
    <title>Login</title>
    <h2>Login page</h2>
    </head>

    <body>
        <form method="POST" action="<?php echo "$PHP_SELF";?>"<font face="Arial">
        <fieldset>
            <b><font size="2">Email: </font></b><input type="text" name="Login_email" size="40" maxlength="255"><br\>
            <b><font size="2"><br>Password: </font></b><input type="password" name="Password" size="16" maxlength="255"><br\>
            <input type="submit" name="submit" value="Login!"><font size="2"> </font>
        </fieldset>
        </form>
        <p>If you have yet to register for an account please follow the link below to create one.</p><p><font face="Arial" size="2"><a href="register.php">Register for an account</a></font></p>
    </body>

    <?
    }
    ?>
</html>
[/code]

Now i'm not really bothered about session id's or tracking ip's so i took that out. I needed to put the session_start at the top on my login page in order to get rid of my errors. I'll perhaps try to move it to after i have successfully matched passwords etc so a session does not start if i have any validation problems.

One problem i am having is getting any info into my session table. I can create the session table when my login.php runs initially but when i log in then check the contents of my table all i get is an empty set. I cannot see where the problem lies. Any idea?

Share this post


Link to post
Share on other sites
I'll have to look over your code to be able to make suggestions on changes, but don't fear session_start(). session_start() does not mean that the user is logged in. It only means that you have a session where you can store information that will carry throughout the domain. With my particular script the session is not used for anything except creating a unique identifier for the individual that comes to the site.

I think I'll probably work on a "lite" version later.

Share this post


Link to post
Share on other sites
To txmedic03,

I have been scratching my head for about a week trying to come up with a solution to limiting the number of logins a user can have, and this little forum topic did the trick. Your examples worked great. I already had an authentication for logging in I just added the sessions table and the checks by adding the first part of your code at the top of each page.

I use PEAR so I had to make adjustments to the code for my queries but all in all it was pretty simple. It works great!

Thanks for your contributions, you saved me a lot of time!

Share this post


Link to post
Share on other sites

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.