views:

338

answers:

3

I have a PHP authentication system on my website using the $_SESSION variable.

A form submits a username and password to the file "login.php". It is handled like this:

<?php include '../includes/sessionstart.inc.php'; ?>
<?php ob_start(); ?>

if($_POST){
    $q = mysql_query("SELECT id, company FROM users WHERE username = '".mysql_real_escape_string($_POST['username'])."' AND password = '".md5($_POST['password'])."'");
    if(mysql_num_rows($q) >= 1){
        $f = mysql_fetch_Array($q);
        $_SESSION['company'] = $f['company'];
        $_SESSION['id'] = $f['id'];
        $_SESSION['logedin'] = true;
        session_write_close();

        ob_clean();
        header("Location: index.php");

}

Afterwards, index.php is loaded and checks whether 'logedin' is true.

<?php include '../includes/sessionstart.inc.php'; ?>
<?php if(!isset($_SESSION['logedin'])) header('Location: login.php'); ?>

On my production server, it continues, but on my Wampserver, it reverts back to login.php. I notice that Wampserver is very slow in page loading, this might have to do something with it. That's why I included the session_write_close, to make sure session data is saved before the pages are switched, but it doesn't help.

The contents of session_start.inc.php are simply:

<?php
    session_start();
?>

I used to have more code in there, but at the moment it's just this. The problem also existed before I started using an include file.

Does anybody have an idea what I'm doing wrong? Why doesn't Wampserver transmit my SESSION data to the next PHP file?

+2  A: 

First of all: the index logedin seems strange for keeping track of a user being logged in. Is this just a typo on SO, or really a code-typo?

Second (depending on the desired behavior), try another approach for making pages login-protected. Your page should look something like

<?php
  include 'login.inc.php';

  if(authorized()) {
    // put some more script here, if needed
    ?>
    // put some plain HTML here  
    <?php
  }
?>

Where login.inc.php handles the session, cookies. In particular, the authorized function should return TRUE if a client is already logged in. If a client is not logged in, it should display a form with action $_SERVER['PHP_SELF'] and return FALSE. If you name the submit-input something like login_submit, you can let login.inc.php handle the verification.

This way, you don't need to refer users to a dedicated login page, and after logging in, user are directly shown the requested page. You can tweak this a bit to make query-strings persistent through login as well.

Martijn
The 'logedin' is an inherited typo from the previous developer working on this project.
littlegreen
Thanks.. I implemented your approach, the code is much more tidy now and the login falls through to the actual page instead of doing the redirect. Although I'm still not sure what caused the problem, I have a solution, and that's most important!
littlegreen
+1  A: 

Try to replace

if($_POST){...}

with

if( isset($_POST['username']) && isset($_POST['password']) ){...}

... at least for debugging purposes. It's possible that some different settings are causing a non-empty $_POST array where it's not expected.

Also, your code seems to be missing exit() calls after header() redirections. Sending an HTTP Location header doesn't automatically stop your script.

Álvaro G. Vicario
thanks.. i was already busy implementing Martijn's approach, stumbled upon the if($POST){...} line and corrected it myself. Nice that you also mention it. I'll also check for missing exit calls.
littlegreen
A: 

After a long time I have fixed this bug finally.

On my localhost WAMP, the session data is not saved between page loads, because the session data is stored in a cookie, and there is no cookie domain to be set for localhost.

The solution:

'session.cookie_domain' should be set to empty string for all local domain names, not only for 'localhost' (but should not be empty for local IP addresses):

<?php
ini_set('session.cookie_domain', (strpos($_SERVER['HTTP_HOST'],'.') !== false) ? $_SERVER['HTTP_HOST'] : '');
?>

Thanks to Marcin Wiazowski who posted it here.

littlegreen