Page 1 of 1

Problem while trying to set cookie in login form

Posted: Tue Jan 20, 2009 9:33 am
by Sindarin
I am creating a login script which supports members. I am using cookies to determine if the user is logged in but when I try to set the cookie I get:
Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\mylogin\login.php:17) in C:\xampp\htdocs\mylogin\login.php on line 78
It seems the setcookie function is a header type function and will not allow any html output before it. Is there any other way to make it work except redirect to a new php page?

Code: Select all

<?php
 
if (isset($_COOKIE['LoggedInStatus']))
{
/* ACCESS LOCKED AREA IF COOKIE EXISTS */
if ($_GET['action']=='logout')
{
/*  LOGOUT  */
setcookie("LoggedInStatus", 0, time()-86400);
header('Location: login.php');
}
echo "You are logged in!<br/><a href='index.php?action=logout'>Logout</a>";
}
else
{

echo "<a href='index.php?action=register'>Register</a>";
 
/*  REGISTER NEW ACCOUNT */
if ($_GET['action']=='register')
{
 
//get user data
$username="sindarin";
$password="123";
$email="info@mymail.com";
$account_type="admin";
$date_registered=date('Y-m-d h:i:s');
$date_lastlogin=date('Y-m-d h:i:s');
 
//convert password to md5 hash
$password=md5($password);
 
//insert user to database
$db_insert="
INSERT INTO users 
(
user_name,
user_password,
user_email,
user_account_type,
user_date_registered,
user_date_lastlogin
)
VALUES
(
'$username',
'$password',
'$email',
'$account_type',
'$date_registered',
'$date_lastlogin'
)";
if (mysql_query($db_insert,$db_connection)){
 
echo "<br/>Registered Successfully!";
}else{mysql_error();}
}
 
/* CHECK LOGIN */
if ($_GET['action']=='login')
{
$username=$_POST['username'];
$password=$_POST['password'];
$password=md5($password);
echo "<br/>Attempt to login:<br/>";
 
$db_select = " SELECT * FROM users WHERE user_name='$username' ";
$db_fetch = mysql_query($db_select,$db_connection);
while($row = mysql_fetch_array($db_fetch))
{
        $get_username=$row['user_name'];
        $get_password=$row['user_password'];
}
        if ($get_password==$password && $get_username==$username && isset($username) && isset($password))
        {
        //this is where the problem is
        setcookie("LoggedInStatus", 1, time()+86400);
        echo "Username & Password is correct!";
        }
        else
        {
        echo "incorrect login details!";
        }
 
 
}
 
/*  LOGIN FORM  */
echo "
<br/>
Login
<br/>
<form id='form1' name='form1' method='post' action='index.php?action=login'>
  <p>
    <input name='username' type='text' id='username' />
</p>
  <p>
    <input name='password' type='text' id='password' />
</p>
  <p>
    <input name='Login' type='submit' id='Login' value='Login' />
  </p>
</form>
 
<br/><br/>
<a href='index.php?action=forgotpassword'>Forgot Password</a>
";
 
}
?>
Also, is my method secure?

Re: Problem while trying to set cookie in login form

Posted: Tue Jan 20, 2009 9:36 am
by Burrito
you'd be better off using sessions.

if you really want to use cookies though, you'll have to either redirect them client side (meta refresh, javascript:location etc) or use the buffer functions.

Re: Problem while trying to set cookie in login form

Posted: Tue Jan 20, 2009 9:45 am
by Sindarin
buffer functions?
you'd be better off using sessions.
I used to use sessions but a friend told me cookies are more secure because they are only created by the site that uses them while sessions can be faked.

Re: Problem while trying to set cookie in login form

Posted: Tue Jan 20, 2009 9:51 am
by Burrito
Sindarin wrote:I used to use sessions but a friend told me cookies are more secure because they are only created by the site that uses them while sessions can be faked.
other way around...

ob*() functions: ob_start() etc (they're all listed on the left side of that page)

Re: Problem while trying to set cookie in login form

Posted: Tue Jan 20, 2009 12:23 pm
by Sindarin
other way around...
are you sure about that? Most articles I found on the web say that cookies are more secure.
Maybe I could use both at once?

Re: Problem while trying to set cookie in login form

Posted: Tue Jan 20, 2009 12:25 pm
by Burrito
cookies are text files saved locally on the client's machine. They can be manipulated by a savvy user. Sessions are variables (usually referenced by a temporary cookie) that are saved on the server so there is no way a user can manipulate them.

....yes I'm sure.

Re: Problem while trying to set cookie in login form

Posted: Tue Jan 20, 2009 12:41 pm
by Sindarin
I know I am not supposed to trust anything client-based, I was just checking.

Is this any better?

Code: Select all

<?php
session_start();
 
//setcookie("LoggedInStatus", 1, time()+86400);
if (isset($_COOKIE['LoggedInStatus']) && $_SESSION['LoggedInStatus']==true)
{
/* ACCESS LOCKED AREA IF COOKIE EXISTS */
if ($_GET['action']=='logout')
{
/*  LOGOUT  */
$_SESSION['LoggedInStatus']=false;
session_destroy();
setcookie("LoggedInStatus", 0, time()-86400);
header('Location: index.php');
}
echo "You are logged in!<br/><a href='index.php?action=logout'>Logout</a>";
}
else
{

echo "<a href='index.php?action=register'>Register</a>";
 
/*  REGISTER NEW ACCOUNT */
if ($_GET['action']=='register')
{
 
//get user data
$username="sindarin";
$password="123";
$email="info@mymail.com";
$account_type="admin";
$date_registered=date('Y-m-d h:i:s');
$date_lastlogin=date('Y-m-d h:i:s');
 
//convert password to md5 hash
$password=md5($password);
 
//insert user to database
$db_insert="
INSERT INTO users 
(
user_name,
user_password,
user_email,
user_account_type,
user_date_registered,
user_date_lastlogin
)
VALUES
(
'$username',
'$password',
'$email',
'$account_type',
'$date_registered',
'$date_lastlogin'
)";
if (mysql_query($db_insert,$db_connection)){
 
echo "<br/>Registered Successfully!";
}else{mysql_error();}
}
 
/* CHECK LOGIN */
if ($_GET['action']=='login')
{
$username=$_POST['username'];
$password=$_POST['password'];
$password=md5($password);
echo "<br/>Attempt to login:<br/>";
 
$db_select = " SELECT * FROM users WHERE user_name='$username' ";
$db_fetch = mysql_query($db_select,$db_connection);
while($row = mysql_fetch_array($db_fetch))
{
        $get_username=$row['user_name'];
        $get_password=$row['user_password'];
}
        if ($get_password==$password && $get_username==$username && isset($username) && isset($password))
        {
        //this is where the problem is
        if ($_POST['remember']==1)
        {
        setcookie("LoggedInStatus", 1, time()+86400);
        $_SESSION['LoggedInStatus']=true;
        echo "Username & Password is correct! | Persistent login";
        }
        else
        {
        setcookie("LoggedInStatus", 1);
        $_SESSION['LoggedInStatus']=true;
        echo "Username & Password is correct! | Session only Login";
        }
        }
        else
        {
        echo "incorrect login details!";
        }
 
 
}
 
/*  LOGIN FORM  */
echo "
<br/>
Login
<br/>
<form id='form1' name='form1' method='post' action='index.php?action=login'>
  <p>
    <input name='username' type='text' id='username' />
</p>
  <p>
    <input name='password' type='text' id='password' />
</p>
  <p>
    <input name='Login' type='submit' id='Login' value='Login' />
  </p>
  <p><input name='remember' type='checkbox' id='remember' value='1' />
Remember Me</p>
</form>
 
<br/><br/>
<a href='index.php?action=forgotpassword'>Forgot Password</a>
";
 
}
?>

Re: Problem while trying to set cookie in login form

Posted: Wed Jan 21, 2009 5:21 am
by Sindarin
Can someone please help me with this?

Re: Problem while trying to set cookie in login form

Posted: Wed Jan 21, 2009 6:09 am
by panic!
I think there might be something wrong with the way you're coding if you're setting cookies after html has been outputted.

I would say it's best to:

1) do all the logic for the page
2) output the way the page is going to look based on the logic above.

Rather than jumbling

write the header, do some sql, output a form, set a cookie, fetch a text file, output the text file, write the fooder

I'd prefer do this

get the sql, set the cookie, fetch a text file. (all your variables and logic are prepared)

followed by

write the header, write the form, output the text file, write the footer

that said:

just put ob_start() at the top of all of the code for this page and that should sort it out, but it's not an ideal solution :)

Re: Problem while trying to set cookie in login form

Posted: Wed Jan 21, 2009 7:57 am
by Sindarin
ob_start(); works great!
Is ob_end_flush(); mandatory at the end of the file?

Hmm, $_SESSION['LoggedInStatus'] expires when the user closes the browser

I used to check only the cookie value but I thought it'd not be secure so I added a session variable as well, but session expires each time the user closes the browser so this
# if (isset($_COOKIE['LoggedInStatus']) && $_SESSION['LoggedInStatus']==true)
does not work properly...


My plan B would be to store a hash of the user's password and username in cookies and check those instead with not using sessions.

Re: Problem while trying to set cookie in login form

Posted: Wed Jan 21, 2009 8:41 am
by mattpointblank
Yeah, sessions only last during the duration of that, er, session.

Your cookie method sounds fairly typical. If I was you though, I'd store just a random (unique!) hash in the cookie so if it gets compromised, an attacker can't find anything useful. Then just store the random unique hash in the database along with the user info.

Re: Problem while trying to set cookie in login form

Posted: Thu Jan 22, 2009 8:29 am
by Sindarin
Okay it's finally finished, here is the login form:

Code: Select all

 
<?php
 
//check if cookie has been set on user's machine
if (isset($_COOKIE['username']) && isset($_COOKIE['password']) && isset($_COOKIE['accessid']))
{
//get values from cookies
$username=$_COOKIE['username'];
$password=$_COOKIE['password'];
$accessid=$_COOKIE['accessid'];
 
//filter values for SQL query
$username=mysql_real_escape_string($username);
$password=mysql_real_escape_string($password);
$accessid=mysql_real_escape_string($accessid);
 
//search the database for that user
$db_select = " SELECT * FROM users WHERE user_name='$username' AND user_password='$password' AND user_access_id='$accessid'";
$db_fetch = mysql_query($db_select,$db_connection);
 
while($row = mysql_fetch_array($db_fetch))
{
        $get_username=$row['user_name'];
        $get_password=$row['user_password'];
        $get_accessid=$row['user_access_id'];
}
//check if the values in cookies and database match
        if ($get_username==$username && $get_password==$password && $get_accessid==$accessid)
        {
//LOGIN SUCCESSFUL - display the rest of the page
        echo "(Login was permitted)<br/>";
        }
        else
        {
//one or more cookies are not valid, have changed or are expired - clear all cookies
header('Location: user-logout.php');
        exit;
        }
 
}
else
{
 
//user doesn't have login info in his cookies - proceed to login form
 
/*  REGISTER NEW ACCOUNT */
if ($_GET['action']=='register')
{
require_once('user-register.php');
}
/*  FORGOT PASSWORD */
if ($_GET['action']=='forgotpassword')
{
require_once('user-forgot.php');
}
 
/* CHECK LOGIN */
if ($_GET['action']=='login')
{
echo "<br/>Logging in...<br/>";
 
//GET form values
$username=$_POST['username'];
$password=$_POST['password'];
$password=md5($password);
 
//small delay
sleep(2);
 
//filter values for SQL query
$username=mysql_real_escape_string($username);
$password=mysql_real_escape_string($password);
 
//search user in database
$db_select = " SELECT * FROM users WHERE user_name='$username' AND user_password='$password' ";
$db_fetch = mysql_query($db_select,$db_connection);
while($row = mysql_fetch_array($db_fetch))
{
        $get_username=$row['user_name'];
        $get_password=$row['user_password'];
        $get_access_id=$row['user_access_id'];
        $get_account_type=$row['user_account_type'];
}
        if ($get_password==$password && $get_username==$username && isset($username) && isset($password))
        {
        //if the user has set to be remembered store that in a cookie
        if ($_POST['remember']==1)
        {
        setcookie("username", $username, time()+60*60*24*365);
        setcookie("password", $password, time()+60*60*24*365);
        setcookie("accessid", $get_access_id, time()+60*60*24*365);
        echo "Username & Password is correct!<br/>You will be logged in until you choose to logout or clear your browser cookies<br/>";
        echo "<a href='index.php'>Reload</a><br/>";
        }
        else
        {
        setcookie("username", $username);
        setcookie("password", $password);
        setcookie("accessid", $get_access_id);
        echo "Success: Username & Password is correct!<br/>You will be logged in until you close your browser<br/>";
        echo "<a href='index.php'>Reload</a><br/>";
        }
        }
        else
        {
        /* INCORRECT LOGIN - deny access */
        echo "<br/>Error: Incorrect login details!<br/>";
        }
        
}
 
/*  LOGIN FORM  */
echo "
<br/>
<b>Login</b>
<br/>
<form id='loginform' name='loginform' method='post' action='index.php?action=login' style='background-color:#999999;padding:3px;width:250px;height:auto'>
 <p>
   User Name <input name='username' type='text' id='username' />
</p>
 <p>
   Password <input name='password' type='password' id='password' />
</p>
 <p>
   <input name='Login' type='submit' id='Login' value='Login' />
 </p>
 <p><input name='remember' type='checkbox' id='remember' value='1' />
Remember Me</p>
<p><a href='index.php?action=forgotpassword'>Forgot Password</a></p>
</form>
 
<a href='index.php?action=register'>Register Account</a>
";
exit;
}
 
?>
 
I used a random hash as suggested and stored it in a cookie/database along with username and hashed password, so touch one cookie, you corrupt them all.

I think this is pretty secure, I don't know what more I could do to secure it better.