Link to home
Start Free TrialLog in
Avatar of APD Toronto
APD TorontoFlag for Canada

asked on

PHP Login Does Not Maintain

Hi Experts,

I have an application that I did and has been working flawlessly for 5 years. Currently I need to move it from one Linux server to another, and my development server is IIS.

On the new server I can successfully login and the first page comes up, but when I try to take any action from there, the redirect from the following code takes place.

//Login Check 
/*    
echo '<br> check sec sess = ' . $_SESSION['sess_id']; 
echo '<br> check sec server sess = ' . session_id(); 
echo '<br> is logging in = ' . $isLoggingIn; 
echo '<br> is logging in set = ' . isset($isLoggingIn); 
*/

    if ($isLoggingIn == FALSE){
        if (!isset($_SESSION['sess_id']) || ($_SESSION['sess_id'] != session_id())){

            header('Location:' . $env['url'] . '/?type=err&msg=Must Login First.');
            exit();
        } 
    }
   

Open in new window


Upon successful login I do $_SESSION['sess_id'] = session_id(); but my gut feeling tells me that the session on the new server, which is VPS at Bluehost, is too short? How can I check this, and also check if debugging is true?

However, I can be completely off track here, so any other assumptions would be appreciated.

Thanks,
Avatar of Zakaria Acharki
Zakaria Acharki
Flag of Morocco image

Several things could lead to this problem, you need to perform some checks like :

1 - Make sure session_start(); is called before any sessions are being called. So a safe bet would be to put it at the beginning of your page, immediately after the opening <?php declaration before anything else. Also ensure there are no whitespaces/tabs before the opening <?php declaration.
2 - After the header redirect, end the current script using exit(); (Others have also suggested session_write_close(); and session_regenerate_id(true), you can try those as well, but I'd use exit();).
3 - Make sure cookies are enabled in the browser you are using to test it on.
4 - Ensure register_globals is off, you can check this on the php.ini file and also using phpinfo(). Refer to this as to how to turn it off.
5 - Make sure you didn't delete or empty the session
6 - Make sure the key in your $_SESSION superglobal array is not overwritten anywhere
7 - Make sure you redirect to the same domain. So redirecting from a www.yourdomain.com to yourdomain.com doesn't carry the session forward.
8 - Make sure your file extension is .php (it happens!)

PHP session lost after redirect
Look at phpinfo() and make sure that your 'session_save_path" is one that is writeable by you.
Avatar of APD Toronto

ASKER

I will check the path.

I can also verify under Chrome cookies, the PHPSEESSID value remains the same even after the code executes above. I'm guessing this means that the session is still aalive?
Not completely.  The session cookie will be set even if you couldn't save the $_SESSION data for some reason.  That's why the path being writeable is important.
As I am not a Linux guy, I will get on Bluehost chat support, but I noticed they are not very good.

In the meanwhile, is there a way to check if path is writible, maybe by writing a .txt file to it. Keeping in mind that on my local machine I have Windows and the session.save_path is c:\php\tmp while on the server it is       /var/cpanel/php/sessions/ea-php56
/var/cpanel/php/sessions/ea-php56 is the 'standard' path for Linux with PHP 5.6.  I have that on a number of machines on shared hosting and I don't have any problems with it.  I thought the problem was on the Windows machine.
No, the problem is on the Linux machine. The Windows machine does not have any issues.

Are you saying that the path suspicion is ruled out.
Now I am performing the same test as this morning. On my Windows machine when I login I see a cookie created, when I logout the cookie is deleted - thisis expected. On Linux when I login there is no cookie created.
I think I am on to something...

I created this simple prototype, which is based on my application flow

index.php
<?php
  
    if (session_start() == FALSE) {    
        $error = 'Please enable cookies, then refresh this page.'
                . '<br><br> This error must be resolved before logging in.';
    } 
?>
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <a href="login.php">Click Here To Login</a>
    </body>
</html>

Open in new window


login.php
<?php

    session_start();
    
    $env = array();
    $env['domain'] = '192.168.2.200';
    
     logout(); //destroy previous sessions.
    $lifetime = 60 * 60 * 0.5; // 0.5h in seconds
    session_set_cookie_params($lifetime, '/', $env['domain'], TRUE, FALSE);
    
    
    $user = array();
    $user['id'] = 1;
    $user['name'] = 'John';
    
    $_SESSION['user'] = $user;
    
    header('Location: result.php');
    exit();

    function logout(){
    
        if (!isset($_SESSION)){
            session_start();
        }

        // Unset all of the session variables.
        $_SESSION = array();


    }
    
?>

Open in new window


result.php
<?php
session_start();
print_variable($_SESSION, 'sess');

function print_variable($var, $label, $raw = true){

    echo '<br>=========START=========<br>';
    echo '<b>' . $label . '</b>';

    if ($raw == true) echo '<pre>';

    print_r($var);

    if ($raw == true) echo '</pre>';
    echo '<br>=========END=========<br>';
}
?>

Open in new window


On both Windows and Linux the result is the following
=========START=========
sess
Array
(
    [user] => Array
        (
            [id] => 1
            [name] => John
        )

)

=========END=========

Open in new window


This is expected, but on Windows when I refresh result.php  I get the same output. However, when I refresh on Linux, I get
=========START=========
sess
Array
(
)

=========END=========

Open in new window


...an empty array. Meaning, the session under Linux server is not kept array, which makes sense when thinking about my original issue, but how to remedy this?
Please read this page: http://php.net/manual/en/function.session-set-cookie-params.php  It appears that you are using session_set_cookie_params wrong.  From that page:
you need to call session_set_cookie_params() for every request and before session_start() is called.

An important thing to remember is that on shared hosting, there are many things that you can't actually change.  One of them is the session timeout.  Since many users share the PHP code, the lowest timeout wins which is normally the standard timeout.
I just found that with my prototype above, the result is correct in both Firefox and Safari, but not in Chrome, which is my and my client default browser.

Also, the same code is working as expected in Chrome from my local machine.

I am guessing that it is a Chrome setting, pertaining to the domain on my live server, or IP Address?
I don't know why you would say that since the 'man' page clearly says that the session_set_cookie_params() Must come before session_start() to work properly.  AND... that it must be on Every page in the session.  Browsers try to make the best of what they are given.  It helps if you give them the correct info.
I did add session_set_cookie_params() on every page, but the issue persists.

I also edited my hosts file to point to the old server, which is Rackspace, uploaded the same prototype and it works In Chrome!

I comment out the hosts file entry to point to the new Bluehost server, and it does not work in Chrome.

Bluehost support is horrible and they even hangup when they hear "Custom"

Oh, both Rackspace and Bluehost are Linux VPS environments.

What do you think about https://stackoverflow.com/questions/8334775/bluehost-or-php-script-issue-with-cookies it does not make much sense, but I cannot decide if it is a sever issue or Chrome issue?
The StackOverFlow article is not about session cookies but otherwise I agree with the answer.

I suggest you create a set of test pages that do Not use session_set_cookie_params() and see what you get.

One other thing.  Chrome is the pickiest about cookies.  It will not accept a cookie on 'localhost' because that is not a unique domain.  Maybe it doesn't like using the IP address to set the cookie?

Below is a PHP program I use to display all cookies set by a site and reported to PHP.
<?php 
error_reporting(E_ALL);

ob_start();
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>PHP Cookie Display</title>
</head>
<body>
<h1>PHP Cookie Display</h1>
<a href="CookieDisplayGeneric.php">CookieDisplayGeneric.php</a><br><br>

<?php
$cukarr = array();
//reset($_COOKIE);
foreach($_COOKIE as $key => $value) {
		$cukarr[] = $key;
    echo "<b>$key :</b> $value<br />\n";
}

ob_end_flush();
?>

</body>
</html>

Open in new window

Dave, I am not sure how your code will test the scenario because you will need at least 2 pages. One to set the session array, and the other to display it. As mentioned Chrome on the new server does not display the array, while other browsers do even after refreshing results.php  as it should.

However, Chrome on my iPad and iPhone work as the other browsers; while Chrome for Windows does not work on the new server, but it does on the old one. As well , Chrome for Windows also works with my localhost.

Considering your advice above, I have modified the code as such

index.php
<?php
  
    if (session_start() == FALSE) {    
        $error = 'Please enable cookies, then refresh this page.'
                . '<br><br> This error must be resolved before logging in.';
    } 
?>
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <a href="login.php">Click Here To Login</a>
    </body>
</html>

Open in new window


login.php
<?php

    $env = array();
    //$env['domain'] = '192.168.2.200';
    $env['domain'] = 'rs-test.citysightseeingtoronto.com';
    
    $lifetime = 60 * 60 * 0.5; // 0.5h in seconds
    session_set_cookie_params($lifetime, '/', $env['domain'], TRUE, FALSE);
    session_start();
    
     logout(); //destroy previous sessions.
    
    
    $user = array();
    $user['id'] = 1;
    $user['name'] = 'John';
    
    $_SESSION['user'] = $user;
    
    header('Location: result.php');
    exit();

    function logout(){
    
        if (!isset($_SESSION)){
            session_start();
        }

        // Unset all of the session variables.
        $_SESSION = array();


    }
    
?>

Open in new window


result.php
<?php

    $env = array();
        //$env['domain'] = '192.168.2.200';
    
     $env['domain'] = 'rs-test.citysightseeingtoronto.com';
        
    $lifetime = 60 * 60 * 0.5; // 0.5h in seconds
    session_set_cookie_params($lifetime, '/', $env['domain'], TRUE, FALSE);
    
    session_start();
    print_variable($_SESSION, 'sess');

function print_variable($var, $label, $raw = true){

    echo '<br>=========START=========<br>';
    echo '<b>' . $label . '</b>';

    if ($raw == true) echo '<pre>';

    print_r($var);

    if ($raw == true) echo '</pre>';
    echo '<br>=========END=========<br>';
}
?>

Open in new window


You can run this code at https://rs-test.citysightseeingtoronto.com/_test/login_session/ this is the new server, and you can see the phpinfo at https://rs-test.citysightseeingtoronto.com/phpInfo.php

Using Chrome if you get the array to display, do a refresh and it will dissapear. This should not be the case, because a refresh means a page change. With the other browsers, the array displays after many refreshes.

Now if you add the following entry to your hosts file and pointed to the old server you will note that Chrome is working perfectly as with the other browsers

	104.239.166.138	rs-test.citysightseeingtoronto.com  # points to Rackspace

Open in new window


Once again, this code is working fine on localhost and Rackspace, but not on Bluehost. So it is probably a server setting?
If you open my code in one window and your code in another in the same site (in the same browser), it will display all the $_SESSION data that currently exists.  $_SESSION data is common to all of the PHP code running on that site on that server.  Just refresh my page when you want to see what the $_SESSION data is at that moment.  I have another similar program for displaying cookies.
but still, I'm not further in solving my issue.
OK, I relized you're testing if cookies are being maintained.

I added your code to both servers, and yes cookies are maintained.  I manually deleted the cookie from after testing one server, then re-tested and refreshed multiple times, and while the PHPSESSID is different server to server, it is the same one the server even afterrefreshing.

So, this means cookies are fine, but the issue is that I'm loosing session.  Why?
In both Firefox and Chrome, you can press Ctl-Shft-I and look at the 'console' where errors are reported.  Firefox and Chrome don't always report the exact same things but you might be able to find some difference that way.
Now I am out, but keep reading that this may happen if favicon.ico is missing. Could it be that simple???
Adding the favicon seemed to help, but when I closed down the browser then reopen it, the same issue. Even what I mentioned the $_COOKIE was working, now it is not.

I am becoming confused and cannot seem to structure my testing anymore on this issue.
I don't think the favicon has anything to do with it.  This PHP page displays both the $_SESSION data and the Cookies.
<?php 
error_reporting(E_ALL);
session_start();  // This joins the current session

?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>PHP Cookie Display</title>
</head>
<body>
<h1>$_SESSION data</h1>
<?php 

foreach($_SESSION as $key => $value) {
	echo "$key => $value<br>";
	}

 ?>
<h1>PHP Cookie Display</h1>
<?php
$cukarr = array();
foreach($_COOKIE as $key => $value) {
		$cukarr[] = $key;
    echo "<b>$key :</b> $value<br />\n";
}
?>

</body>
</html>

Open in new window

This morning I re-tested and it is not working on ALL browsers, I guess it was cached.

Your code is using foreach with echo, mine uses print_r which is the same thing.

Comsidering it's on all browsers (see URLs above), I'm assuming it's a server setting, and Blue Host is unwilling to help.

What do you think I should be looking at? As well, I'd Ctrl+F5 sufficient to test after switching my hosts file? How should I be testing?

Can it be that sometimes it's saving some times not... I guess at random.?
I doubt that it's random.  Let me think about it and I'll post some test files.
I'm not sure what we're looking for here except that it's something out of place or wrong.  Below are three files, sdc.php, sdc2.php, and sdc3.php.  They each set a session variable.

sdc.php
<?php 
error_reporting(E_ALL);
session_start();  // This joins the current session
$_SESSION['sdc'] = "sdc";

?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>PHP Cookie Display</title>
</head>
<body>
<a href="sdc2.php">sdc2.php</a>
<h1>$_SESSION data</h1>
<?php 

foreach($_SESSION as $key => $value) {
	echo "$key => $value<br>";
	}

 ?>
<h1>PHP Cookie Display</h1>
<?php
$cukarr = array();
foreach($_COOKIE as $key => $value) {
		$cukarr[] = $key;
    echo "<b>$key :</b> $value<br />\n";
}
?>

</body>
</html>

Open in new window


sdc2.php
<?php 
error_reporting(E_ALL);
session_start();  // This joins the current session
$_SESSION['sdc2'] = "sdc2";

?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>PHP Cookie Display</title>
</head>
<body>
<a href="sdc3.php">sdc3.php</a>
<h1>$_SESSION data</h1>
<?php 

foreach($_SESSION as $key => $value) {
	echo "$key => $value<br>";
	}

 ?>
<h1>PHP Cookie Display</h1>
<?php
$cukarr = array();
foreach($_COOKIE as $key => $value) {
		$cukarr[] = $key;
    echo "<b>$key :</b> $value<br />\n";
}
?>

</body>
</html>

Open in new window


sdc3.php
<?php 
error_reporting(E_ALL);
session_start();  // This joins the current session
$_SESSION['sdc3'] = "sdc3";
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>PHP Cookie Display</title>
</head>
<body>
<a href="sdc.php">sdc.php</a>
<h1>$_SESSION data</h1>
<?php 

foreach($_SESSION as $key => $value) {
	echo "$key => $value<br>";
	}

 ?>
<h1>PHP Cookie Display</h1>
<?php
$cukarr = array();
foreach($_COOKIE as $key => $value) {
		$cukarr[] = $key;
    echo "<b>$key :</b> $value<br />\n";
}
?>

</body>
</html>

Open in new window


They are all the same except for the link and the $_SESSION data that is set.
When I ran Dave's code, and enhanced a little, it passed all scenarios, but I was still having the issue. So, I took apart my production code and  summarized it into the following 4 files, which are less than 100 lines and I am able to replicate this issue.

index.php
<?php
  
    if (session_start() == FALSE) {    
        $error = 'Please enable cookies, then refresh this page.'
                . '<br><br> This error must be resolved before logging in.';
    } 
?>
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <a href="login.php">Click Here To Login</a>
    </body>
</html>

Open in new window


gen_incl.php
<?php 
session_start();
ob_start();
//echo '<br>session started from gen inc............<br>';
//echo '<br>sess_id from gen inc............' . $_SESSION['sess_id'] . '<br>';

if (!isset($isLoggingIn)) {
    $isLoggingIn = FALSE;
}
//Override server settings
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
date_default_timezone_set('America/Toronto');

//Check Security...

    if ($isLoggingIn == FALSE){
        if (!isset($_SESSION['sess_id']) || ($_SESSION['sess_id'] != session_id())){

            echo "<br>***SECURITY FAIL***<br>";
        
        } else {
            
            echo "<br>***SECURITY PASS***<br>";
            
        }
        
    }
        

?>

Open in new window


login.php
<?php
    //$isLoggingIn = TRUE;
    require_once 'gen_incl.php';
    
    $_SESSION['sess_id'] = session_id();
    $_SESSION['key'] = 'value';
    
    header('Location: result.php');
    die();
    
?>

Open in new window


result.php
<?php

    require_once 'gen_incl.php';
    
    print_variable($_SESSION, '$_SESSION');
    print_variable(session_id(), 'sess_id()');

function print_variable($var, $label, $raw = true){

    echo '<br>=========START=========<br>';
    echo '<b>' . $label . '</b>';

    if ($raw == true) echo '<pre>';

    print_r($var);

    if ($raw == true) echo '</pre>';
    echo '<br>=========END=========<br>';
}
?>

Open in new window


The code above replicates exactly my scenario in logic and results. Where:

On my localhost and on the old Rackspace server, result.php produces the following even after multiple of refreshes and after couple of minutes
***SECURITY PASS***

=========START=========
$_SESSION
Array
(
    [sess_id] => fq16vmn7qk59ivo9ijtm2dboj1
    [key] => value
)

=========END=========

=========START=========
sess_id()
fq16vmn7qk59ivo9ijtm2dboj1

=========END=========

Open in new window


However, on the new Bluehost server I get the same results (different values of course), but when I refresh virtually 2 seconds later, I get
***SECURITY FAIL***

=========START=========
$_SESSION
Array
(
)

=========END=========

=========START=========
sess_id()
h6b11oencgbbf6c3k03fu142q6

=========END=========

Open in new window


which means I keep loosing my session immediately on the Bluehost server, but why and how do I fix?

Again, this replicated everything exactly. I am guessing it is a server setting?
Must be something on the server.  I tried your code on 3 different servers and got the 'correct' results everytime.
Any idea what it could be, or where do I start?
Not really.  Moving to another host is what I would be thinking.
Out of curiosity, so I can make a case, why would you say?
ASKER CERTIFIED SOLUTION
Avatar of Dave Baldwin
Dave Baldwin
Flag of United States of America image

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
Thanks Dave, my client is deciding their options.