APD Toronto
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.
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,
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();
}
}
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,
Look at phpinfo() and make sure that your 'session_save_path" is one that is writeable by you.
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?
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.
ASKER
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/e a-php56
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/e
/var/cpanel/php/sessions/e a-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.
ASKER
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.
Are you saying that the path suspicion is ruled out.
ASKER
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.
ASKER
I think I am on to something...
I created this simple prototype, which is based on my application flow
index.php
login.php
result.php
On both Windows and Linux the result is the following
This is expected, but on Windows when I refresh result.php I get the same output. However, when I refresh on Linux, I get
...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?
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>
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();
}
?>
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>';
}
?>
On both Windows and Linux the result is the following
=========START=========
sess
Array
(
[user] => Array
(
[id] => 1
[name] => John
)
)
=========END=========
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=========
...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:
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.
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.
ASKER
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?
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.
ASKER
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?
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.
I suggest you create a set of test pages that do Not use session_set_cookie_params(
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>
ASKER
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
login.php
result.php
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
Once again, this code is working fine on localhost and Rackspace, but not on Bluehost. So it is probably a server setting?
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>
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();
}
?>
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>';
}
?>
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
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.
ASKER
but still, I'm not further in solving my issue.
ASKER
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?
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.
ASKER
Now I am out, but keep reading that this may happen if favicon.ico is missing. Could it be that simple???
ASKER
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 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>
ASKER
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.?
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
sdc2.php
sdc3.php
They are all the same except for the link and the $_SESSION data that is set.
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>
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>
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>
They are all the same except for the link and the $_SESSION data that is set.
ASKER
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
gen_incl.php
login.php
result.php
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
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
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?
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>
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>";
}
}
?>
login.php
<?php
//$isLoggingIn = TRUE;
require_once 'gen_incl.php';
$_SESSION['sess_id'] = session_id();
$_SESSION['key'] = 'value';
header('Location: result.php');
die();
?>
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>';
}
?>
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=========
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=========
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.
ASKER
Any idea what it could be, or where do I start?
Not really. Moving to another host is what I would be thinking.
ASKER
Out of curiosity, so I can make a case, why would you say?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks Dave, my client is deciding their options.
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
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