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
tr5Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

hieloCommented:
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

0
gemdeals395Commented:
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 :)
0
gemdeals395Commented:
Sorry,
    This should have been:

if(!isset($_SESSION['current_user'])) {
    $_SESSION['current_user'] = (string) '';
}
0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

tr5Author Commented:
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.

0
hieloCommented:
>>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.
0
tr5Author Commented:
>>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.
0
hieloCommented:
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

0
tr5Author Commented:
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.
0
hieloCommented:
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();
0
tr5Author Commented:
Is it possible that there is some setting with the PHP that is wrong?
0
gemdeals395Commented:
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.
0
tr5Author Commented:
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.
0
hieloCommented:
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?
0
gemdeals395Commented:
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.
0
tr5Author Commented:
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
0
gemdeals395Commented:
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.
0
gemdeals395Commented:
Just make sure no matter what session_start() has been called before trying to set up anything :)
0
tr5Author Commented:
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.
0
hieloCommented:
>>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).
0
tr5Author Commented:
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.
0
gemdeals395Commented:
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.
0
tr5Author Commented:
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.
0
gemdeals395Commented:
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 :)
0
hieloCommented:
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()
0
gemdeals395Commented:
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 :)
0
tr5Author Commented:
Here is exactly the same thing:
http://www.thescripts.com/forum/thread1694.html
0
tr5Author Commented:
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.
0
gemdeals395Commented:
What happens if you use:

exit();

right after the redirection?
0
gemdeals395Commented:
Maybe Like this:

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

If that works you'll have to update all header redirects.
0
tr5Author Commented:
Doesn't work.
0
gemdeals395Commented:
On your manage.php have you called session_start() at the top before anything happens?
0
tr5Author Commented:
Yes
0
gemdeals395Commented:
Well it looks like then the only option is going to be passing the session along, you can always just md5() encrypt it. I would really suggest to just write code without using so many redirects. So like as soon as a visitor arrives set up all the _SESSION variables you want to use:

<?php
    session_start();
    if (!isset($_SESSION['securityLevel'])) {
      $_SESSION['securityLevel'] = (int) 0;
    }
   
    if($_SESSION['securityLevel'] == '0') {
        //Not logged in. If this is your manage.php then show the login form.
    } elseif($_SESSION['securityLevel == '1') {
        //Standard User has logged on. Show the regular manage.php
    } elseif($_SESSION['securityLevel'] == '2') {
        //admin has logged on. Show the admin manage.php
    }
?>

Fact is that for whats happening we could keep working on a workaround or just start building your apps not to use those header redirects. I only use those when leaving the site to say use a 3rd party payment processor. When you build each app just use the same page for say manage.php and depending on the security level display the correct part of the application. :)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
tr5Author Commented:
Thank you very much for your help
0
gemdeals395Commented:
Anytime :)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.