Link to home
Start Free TrialLog in
Avatar of tr5
tr5

asked on

Login system with sessions requires logging in twice

Hi
I have a login system which for some reason requires anyone logging in to do so twice. Here is the code:

<?php
session_start();

require "../Utility/db.inc";
require "../Utility/utility_fns.php";

if (!isset($_POST['username']) || !isset($_POST['password']))
{
  header( "Location: http://www.mysite.com/Management/login.html");
}
elseif (empty($_POST['username']) || empty($_POST['password']))
{
  header( "Location: http://www.mysite.com/Management/login.html");
}
else
{
  //add slashes to the username and md5() the password
  $user_login = addslashes($_POST['username']);
  $pass_login = md5($_POST['password']);

  $dblink = db_connect($addr, $db, $user, $pass);

  $sql = "SELECT * FROM users WHERE name='$user_login' AND password='$pass_login';";
  $db_result = do_query($sql, $dblink);
      
  $row_check = mysql_num_rows($db_result);

  if($row_check > 0)
  {
    $row_data = mysql_fetch_array($db_result);
    $_SESSION["user_status"] = TRUE;
    $_SESSION["current_user"] = $user_login;
    header("Location: http://www.mysite.com/Management/manage.php");
  }
  else
  {
    header("Location: http://www.mysite.com/Management/login.html");
  }
}
?>

Any ideas why?
tr5
Avatar of hielo
hielo
Flag of Wallis and Futuna image

The logic looks fine. Try the code below, and everytime you end up on login.html, look at the url and take note of the ?reason=#

Report back the # you are getting for both instances.
<?php
session_start(); 
 
require "../Utility/db.inc";
require "../Utility/utility_fns.php";
 
if (!isset($_POST['username']) || !isset($_POST['password'])) 
{ 
  header( "Location: http://www.mysite.com/Management/login.html?reason=0"); 
} 
elseif (empty($_POST['username']) || empty($_POST['password'])) 
{ 
  header( "Location: http://www.mysite.com/Management/login.html?reason=1"); 
} 
else
{ 
  //add slashes to the username and md5() the password 
  $user_login = addslashes($_POST['username']); 
  $pass_login = md5($_POST['password']); 
 
  $dblink = db_connect($addr, $db, $user, $pass);
 
  $sql = "SELECT * FROM users WHERE name='$user_login' AND password='$pass_login';";
  $db_result = do_query($sql, $dblink);
      
  $row_check = mysql_num_rows($db_result);
 
  if($row_check > 0)
  { 
    $row_data = mysql_fetch_array($db_result);
    $_SESSION["user_status"] = TRUE;
    $_SESSION["current_user"] = $user_login; 
    header("Location: http://www.mysite.com/Management/manage.php"); 
  } 
  else 
  { 
    header("Location: http://www.mysite.com/Management/login.html?reason=2"); 
  } 
} 
?> 

Open in new window

Avatar of gemdeals395
gemdeals395

The reason you have to login twice is because in the superglobal _SESSION the 2 variables you are using are not set yet. Here are the 2 variables you use.

    $_SESSION["user_status"] = TRUE;
    $_SESSION["current_user"] = $user_login;

So in the beginning of your code just check to see if the superglobals

_SESSION['user_status']
_SESSION['current_user']

are set and if not set them in the session. Also change the quotes to single. After you cal session_start() add the following:

if(!isset($_SESSION['user_status'])) {
    $_SESSION['user_status'] = (bool) false;
}

if(!isset($_SESSION['current_user'])) {
    $_SESSION['current_user'] = (varchar) '';
}

Now since the variables have been set they will be able to accept your login credentials on the first login :)
Sorry,
    This should have been:

if(!isset($_SESSION['current_user'])) {
    $_SESSION['current_user'] = (string) '';
}
Avatar of tr5

ASKER

Hielo:
Added the GET string. When the login.html page reloaded after the first login attempt, the URL showed "http://www.mysite.com/Management/login.html" WITHOUT the GET string. So I don't know where that came from.

gemdeals
Added your code. But it didn't make any difference. Still have to login twice.

>>WITHOUT the GET string
Are you sure you are viewing the correct login.html?
Out of curiosity, where does login.html send the login name/password it "collects"? Since it is an HTML page rather than a PHP page, most like it does not do the authentication itself. I am assumming you send the data to some php page.
Avatar of tr5

ASKER

>>Are you sure you are viewing the correct login.html?
Yes. I only have one.
>>where does login.html send the login name/password it "collects"?
to login.php, whose contents you see in my original question.
Try this:
<?php
session_start(); 
 
require "../Utility/db.inc";
require "../Utility/utility_fns.php";
 
//do not authenticate if the user is already authenticated!
//sending to Homepage by default
if( isset($_SESSION["user_status"]) )
{
	header("Location: /");
}
elseif (!isset($_POST['username']) || !isset($_POST['password'])) 
{ 
  header( "Location: http://www.mysite.com/Management/login.html"); 
} 
elseif (empty($_POST['username']) || empty($_POST['password'])) 
{ 
  header( "Location: http://www.mysite.com/Management/login.html"); 
} 
else
{ 
  //add slashes to the username and md5() the password 
  $user_login = addslashes($_POST['username']); 
  $pass_login = md5($_POST['password']); 
 
  $dblink = db_connect($addr, $db, $user, $pass);
 
  $sql = "SELECT * FROM users WHERE name='$user_login' AND password='$pass_login';";
  $db_result = do_query($sql, $dblink);
      
  $row_check = mysql_num_rows($db_result);
 
  if($row_check > 0)
  { 
    $row_data = mysql_fetch_array($db_result);
    $_SESSION["user_status"] = TRUE;
    $_SESSION["current_user"] = $user_login; 
    header("Location: http://www.mysite.com/Management/manage.php"); 
  } 
  else 
  { 
    header("Location: http://www.mysite.com/Management/login.html"); 
  } 
} 
?> 

Open in new window

Avatar of tr5

ASKER

hielo:
Added
//do not authenticate if the user is already authenticated!
//sending to Homepage by default
if( isset($_SESSION["user_status"]) )
{
      header("Location: /");
}

but it made no difference.
Well, I tested the code you posted and it works OK for me. The only "issue" I saw was that if the user gets to login.php he/she should not have to re-authenticate if the user already did so.
What's going on on manage.php? You need to start that with session_start();
Avatar of tr5

ASKER

Is it possible that there is some setting with the PHP that is wrong?
Other than making sure that variables are declared and session_start is fired off there is not alot here to go wrong. If this is your exact code in use I see an extra semi-colon on this line here:

 $sql = "SELECT * FROM users WHERE name='$user_login' AND password='$pass_login';";

should be:

 $sql = "SELECT * FROM users WHERE name='$user_login' AND password='$pass_login'";

And I notice on all your calls to header location you are typing an actual web address like http://www.mysite.com Is this login script located in the same directory as the site your logging into. There is no doubt that whats happening here is when the script runs and you get a successful login a variable is getting set into session then on the next login is holding the variable. First when I debug something like this add a foreach statement and dump the variables to check whats happening every step of the way:

foreach($_SESSION as $var => $val) {
      echo("$var = $val<br>");
}

What I am suspecting is $_SESSION['user_status'] which is false is setting itself up when you login then on the next login becomes true. But this code will dump the variables for $_SESSION to check it.
Avatar of tr5

ASKER

I put
echo "$_SESSION[user_status], $_SESSION[current_user]";
before this line:
header("Location: http://www.mysite.com/Management/manage.php");
and I see "1, bob" after the 1st login attempt.
But of course the header call fails because of the echo.

I just don't understand how login.html  is called again.
You never answered this:
What's going on on manage.php? Could it be sending the user back to loing.html for the wrong reason?
Do you have some code on manage.php that checks the user_status and if not logged on sends them back to login.php? Post your php from manage.php if you have some more header locations running there as well.
Avatar of tr5

ASKER

I am such an idiot. I apologize.

manage.php looks like this:

if( isset($_SESSION["user_status"]) && ($_SESSION["user_status"] == TRUE) )
{
 all the code
}
else
  header( "Location: http://www.cdshowguides.com/Management/login.html");

and this IS the header that is re-calling login.html
Ok, So it seems that when you first come to login.php when you make the first call to $_SESSION['user_status'] it registers in session, then manage.php redirects back since it is still false but now declared in the session then the second pass through it accepts the value. Generally what I normally do is on the index page first thing is fire off session_start, then I write a class that controls setting up & destroying my variables to keep the session cleaned up. Now 1 thing I like to do is run a _SESSION called _SESSION['securityLevel'] where 0 = not logged in, 1 = user logged in, 2 = admin logged in or whatever so I can control exactly whats happening for user management. Now on your logon page try something like this above your form and make those calls to set the session on those 2 variables like this

<?php
if(!isset($_SESSION['user_status'])) {
    $_SESSION['user_status'] = (bool) false;
}

if(!isset($_SESSION['current_user'])) {
    $_SESSION['current_user'] = (string) '';
}
?>

HTML FORM TO LOGIN HERE

and see if you can get those registered before submitting the form.
Just make sure no matter what session_start() has been called before trying to set up anything :)
Avatar of tr5

ASKER

Nope. I added those lines

<?php
session_start();
if(!isset($_SESSION['user_status'])) {
    $_SESSION['user_status'] = (bool) false;
}
if(!isset($_SESSION['current_user'])) {
    $_SESSION['current_user'] = (string) '';
}
?>


 above my form in login.html. Still the same problem!!!
And you are right, in manage.php it fails on the isset($_SESSION['user_status'])

Sorry to waste so much of your time.
>>above my form in login.html.
Those lines need to set in login.php. The HTML page will not execute php code (unless you configured your server to do so, but typically it does not).
Avatar of tr5

ASKER

I set them in login.php. Didn't help.
I also tried putting them in login.html and changed the name to login1.php so that the server would process them. Also did nothing.
try this, at the bottom of your manage.php page do this:

if( isset($_SESSION["user_status"]) && ($_SESSION["user_status"] == TRUE) )
{
 all the code
}
else
{
  //header( "Location: http://www.cdshowguides.com/Management/login.html");
}
foreach($_SESSION as $var => $val) {
    echo("$var = $val<br>");
}


Stop the redirect then look at each session value the first time through and see exactly what's wrong.
Avatar of tr5

ASKER

Tried it. Nothing prints. Seems like SESSION has nothing in it.

Seems like I'm not the only one having this problem (http://bugs.php.net/bug.php?id=14636)
One of the solutions in there was to do this in the header call:
header( "Location:foobar.php?" . Session_Name() . "=" . Session_ID() );
although it is not recommended. I have no idea what it does, but I tried it and worked for me. Although I cut and pasted the URL it generated  to to other browsers and that let me log in without going through the login screen so I guess it is not a solution.
try taking the url out of your redirects and link it like header("Location: /Management/manage.php"); Or whatever the link is and see if you get a change on your redirect. I have read about some people having issues on using http redirects and having session issues. Personally I only use a redirect like that when leaving 1 of my sites generally :)
1. Make sure your browser is configured to accect cookies. Otherwise Sessions do not work, no matter what server technology you are using (PHP,ASP,JSP,etc)
2. that page clearly suggests that you need to make sure that
session.auto_start = 0;
in the php.ini, since your scripts are using session_start()
Actually hielo by default php will store the sessions server side and resort to cookies second however you can change that in php.ini. Let me also ask..... I am assuming your on a Windows machine correct? Are you running Norton Anti-Virus & Firewall? If so shut it off while testing. The Norton Privacy manager thing I have seen mess up more stuff than you can imagine :)
Avatar of tr5

ASKER

Here is exactly the same thing:
http://www.thescripts.com/forum/thread1694.html
Avatar of tr5

ASKER

hielo:
I have session.auto_start = 0; in php.ini
Cookies are enabled

gemdeals:
My server is Linux machine. My client is Windows. I have McAfee AV, and the Windows firewall.
Turning off the ifrewall didn't do anything.
What happens if you use:

exit();

right after the redirection?
Maybe Like this:

session_write_close();
header("Location: ");
exit;

If that works you'll have to update all header redirects.
Avatar of tr5

ASKER

Doesn't work.
On your manage.php have you called session_start() at the top before anything happens?
Avatar of tr5

ASKER

Yes
ASKER CERTIFIED SOLUTION
Avatar of gemdeals395
gemdeals395

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of tr5

ASKER

Thank you very much for your help
Anytime :)