Apache/PHP Session behavior question

In ALL my pages (except the login.php, which simply destroys the session), I have the following code at the very top:

session_name("nd");
session_set_cookie_params(60*60*8); // 8 hours
session_start();
if (isset($_SESSION['user'])) {
    $user = $_SESSION['user']; // This is a User class object
} else {
    /* session expired */
    header("Location: ", 'login.php');
}

Open in new window


I have Windows Explorer open to C:\xampp\tmp, which is where Apache creates the session files. I noticed that every time I traverse to another page, a new session file is created. So after traversing through 5 pages, I now see 5 files. What's bizarre though is that only one of them would contain the User object information at any given time, and the rest are just empty files.

I'm confused! On the one hand, I was assuming there would only be ONE file for my session. But even with all the multiple session files being created, only ONE of them contains the User object data at any given time. So this is telling me that despite multiple files being created, only one of them really contain my session data. Is this normal behavior????

Also, if my code is flawed/lacking in any way, please tell me. This is my first time trying to incorporate session management into a PHP application, so I would appreciate any advice from the more experienced PHP developers among you. Thanks.
elepilAsked:
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.

Dave BaldwinFixer of ProblemsCommented:
I think we may have told you before that most of us never change the session name or cookie params.  There is generally no point in it so we're not sure what you're trying to do.  Have you used the standard example code to see how sessions are intended to work?  I suggest that before you try to do it your way, you try the examples from the sessions pages and see how they work.  http://php.net/manual/en/function.session-start.php  

Note also that a 'session cookie' in all languages has an expiration of 0.  That makes it expire when all the windows of the browser are closed.  http://en.wikipedia.org/wiki/HTTP_cookie#Session_cookie
0
elepilAuthor Commented:
To Dave Baldwin. Thanks for responding.

In the past, my question was about starting and detecting sessions. You guys enlightened me when I realized I always had to start with session_start() to open the session. My questions this time go way beyond that.

I'm not sure what advantage having a session name provides, but when you tell me there is no point, that begs the question, and I ask this for no other reason other than to learn, "why?". Why would PHP provide the ability to give a session a name and serve no purpose? I would like to know the reason, if you have time to explain a bit.

Also, I see many applications out there (usually with banks) that keep track of the session expiration, which I thought was pretty useful. But you say the expiration is '0', which I presume is infinite? How do I implement a finite timed session then that brings the user back to a login after a period of time has lapsed?

The link you provided shows code that starts the session and starts plugging in variable values. I'm thinking I'm past that, so I'm not sure how that's supposed to help me other than imitate code others have done without question. I do understand your point in just trying to 'imitate' the way others do it, but my purpose for making this post is to understand the "why's" as well.
0
Dave BaldwinFixer of ProblemsCommented:
'session_name()' is there because someone wanted it.  On my own servers, I set my own session name in 'php.ini' for no other reason than because I can.  You are confusing several things.  

0. Sessions are intended to identify user information in sessions on the server.  They are Not intended to manage users as such.  This is true in all languages used on web servers such as ASP, ASP.NET, JAVA, and PHP.  Session cookies as I noted above have an expiration of 0.  That tells the browser to delete them when all the browser windows are closed.  That is also normal operation for all browsers and languages.  By the same token... if you set an expiration for a cookie, it is by definition Not considered a session cookie by the browser.

1. The cookie expiration actually has nothing to do with the session expiration on the server.  That is set by 'session.gc_maxlifetime'.  Note that 'gc' stands for Garbage Collection.  And the timer for 'session.gc_maxlifetime' on a particular session is reset on every page access that occurs before it is timed out.

2. Even 'session.gc_maxlifetime' does not set the actual session expiration time.  It sets the Minimum time.  'session.gc_probability' and 'session.gc_divisor' are used to determine whether garbage collection is going to occur during the current script.  If every script invoked garbage collection, that would take a lot of extra time on a busy server.  When garbage collection is done, it is done on all expired sessions at once.

3. When the session expires on the server and garbage collection is done, the $_SESSION variable data is deleted.  It does not matter if your cookie is not expired, the $_SESSION variable data will be gone.
0
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

Dave BaldwinFixer of ProblemsCommented:
There are quite a  few items in 'php.ini' that relate to sessions.  http://php.net/manual/en/ini.list.php
0
elepilAuthor Commented:
To Dave Baldwin.

I appreciate your response. I do remember you, as you've helped me quite a few times in the past, and I am grateful to you and others like you for taking the time to respond to me.

But this time, granted that your response did make me learn some new things, I feel like most of my questions were ignored. Let me reiterate the topics:

I have Windows Explorer open to C:\xampp\tmp, which is where Apache creates the session files. I noticed that every time I traverse to another page, a new session file is created. So after traversing through 5 pages, I now see 5 files. What's bizarre though is that only one of them would contain the User object information at any given time, and the rest are just empty files.

I'm confused! On the one hand, I was assuming there would only be ONE file for my session. But even with all the multiple session files being created, only ONE of them contains the User object data at any given time. So this is telling me that despite multiple files being created, only one of them really contain my session data. Is this normal behavior????

As I read through your two responses so far, I saw nothing that addressed that. But let me tell you why this is a concern to me. With just me testing my application, I'm seemingly generating quite a number of files on the server for having just ONE session. That behavior didn't sit well with me, and I thought maybe I was doing something wrong in my code. Hence, it led to what I said at the end of my post:

Also, if my code is flawed/lacking in any way, please tell me.

I guess you felt my entire code snippet was so invalid that your response was to reproach it but offered no suggestions or alternatives. All you said was
There is generally no point in it so we're not sure what you're trying to do.

My code snippet is very short, and I'm surprised you couldn't be sure what I was trying to do. To me, it was obvious that I was trying to set an expiration for the session, and checking for the presence of the 'user' variable in the session (which simultaneously checks for the existence of a session). Should the session be non-existent (which suggests expiration), then I would redirect the user to the login page.

While I do appreciate (as I always have) the time and effort you have expended in trying to help me, I have to be honest in letting you know that I am left not much different from where I started. Thank you for your time.
0
Dave BaldwinFixer of ProblemsCommented:
It's your method that is confusing.  And your assumptions about session timing are simply wrong.  The expiration of the cookie in the browser and expiration of the session on the server are not tied to each but are actually independent of each other.  I'm puzzled by your refusal to use the 'standard' code at least to compare it to what you are doing.  I use the 'standard' code on many web sites and it works perfectly.

My next post will be from my WAMP machine.  I looked at the C:\wamp\tmp directory.  Garbage collection has probably never been run on that machine.  I have session files from 2010.
0
Dave BaldwinFixer of ProblemsCommented:
I have created the two files below on my WAMP machine.  When I run them and go back an forth between them, there is Only One session file created in C:\wamp\tmp.

slogin.php
<?php 
session_start();
if (isset($_SESSION['user'])) {
    $user = $_SESSION['user']; // This is a User class object
} else {
    $_SESSION['user'] = "TheUser";
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<title>slogin.php</title>
</head>
<body>
<h1>slogin.php</h1>
<?php echo $_SESSION['user']; ?><br />

<a href="sestest1.php">sestest1.php</a>
</body>
</html>

Open in new window


sestest1.php
<?php 
session_start();
if (isset($_SESSION['user'])) {
    $user = $_SESSION['user']; // This is a User class object
} else {
    /* session expired */
    header("Location: slogin.php");
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<title>sestest1.php</title>
</head>
<body>
<h1>sestest1.php</h1>
<?php echo $_SESSION['user']; ?><br />

<a href="slogin.php">slogin.php</a>
</body>
</html>

Open in new window

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
Dave BaldwinFixer of ProblemsCommented:
And if I completely close my browser (Firefox) and then open it up and run them again, then I get a new session file.  That is how it is supposed to work.
0
elepilAuthor Commented:
To Dave Baldwin.

My objectives are two-fold:

1) To understand why a session file keeps getting created on the server for every page I land within my application. (This just feels horribly wrong.)

2) To create a session timeout so that when the user hasn't touched anything in the application after a while, it will go back to the login page.

I don't think it's accurate to say that I won't use the "standard". It's just that the standard way you showed me does not meet my requirements (e.g. no session expiration). All I saw from the "standard" you showed me was simply to do a session_start(), then start plugging in the values I want into the session.

What I'm building is not a traditional website. My project is an attempt to migrate an intranet fat client application written in Adobe Flex (which runs on the Flash Player) with a Java middle tier onto the PHP platform. Session management is critical because I cannot allow a user to land on any page within the application just because they had the URL. If there's no session, I need to redirect them to the login page.

Now should a user go home for the day while leaving the browser up somewhere inside the application, I also need to implement a session timeout where it would automatically log the user off back to the login page after a few hours. I can think of using the JavaScript setInterval() for this, but am interested in looking for a PHP method to do this if I could.

I hope that helps you understand why I have to do things the way I described.
0
elepilAuthor Commented:
To Dave Baldwin.

Hmm.. I'm beginning to think the repeated generation of session files could be an issue with XAMPP. After taking out the session_name and session_set_cookie thing, you and I are doing essentially the same thing.

But your code snippet assumes session expiration can only be caused by one thing -- the shutting down of the browser (which would then kill the session such that trying to land on sestest1.php would bring the user back to a login). In my previous post, I mentioned the scenario of the user leaving for the day with his browser up and inside the application. I know my bank kicks me back to a login all the time after about 30 minutes of inactivity, and that's what I was trying to accomplish.
0
Dave BaldwinFixer of ProblemsCommented:
The standard method using session_start() as I have shown will expire their session in 1440 seconds / 24 minutes.  That is built into the session code.  And as I have said, PHP sessions are for identifying user data, not for controlling user 'sessions'.  Banks and others create their own timers so they can put up a message that "Your session is expiring."  To even know that, you would have to contact the server... which of course extends the PHP session.

As for the multiple session files, all I can think of is that you keep expiring the session by destroying it and starting a new one which will Always create a new session file.  Check your cookies.  They are probably changing too if that is what you are doing.

You can not get to your ultimate goal of controlling user sessions just by using PHP sessions.
0
Dave BaldwinFixer of ProblemsCommented:
I did mention that I have session files from the year 2010 because garbage collection has never run on that machine didn't I?  Even session_destroy() does not run garbage collection to delete the files, it merely kills the data.
0
elepilAuthor Commented:
Dave, 24 minutes?? Surely there must be a way to set that to a specific duration, right? It makes no sense for the session to expire after an oddball number of 24 minutes.

From my studies, I was led to the session_set_cookie_param, but that apparently is incorrect, and now I'm at a loss.

I agree with you that PHP alone will not suffice. I will probably have to use setInterval() as a timer on every page in the application to test for inactivity. If I go that route though, session expiration in PHP now changes from a how-to-do-it scenario into a matter how-to-prevent-expiration, especially if it's set to expire in just 24 minutes. Even googling about this comes up with nothing. I am incredulous that PHP would be constructed this way.
0
Dave BaldwinFixer of ProblemsCommented:
Yes, 1440 seconds, it's right there in 'php.ini' unless you've changed it.  Remember this is an 'inactivity' timer.  And as I keep pointing out, it is at best a minimum setting, not a precise timing.  Note that since those session files from 2010 are still on my WAMP machine, if I could get the session_id value from them, I could reactivate them.  I actually do something like that on a shopping cart for a client.  In that case, it is used to identify the shopping cart as well as change the session.

And note that on shared hosting, even if you have your own 'php.ini', the lowest time that is set on any 'php.ini' on the server will expire and delete all the session data that has been inactive for that time.  The lowest number wins.  That assumes that garbage collection even runs.

For your application, I suggest you store the start time in the database and then reset it when it is needed.  I say that because you are probably going to end up using AJAX or some other code that will reset the PHP session timer anyway.  You don't want the user session to be extended by background activity.
0
Ray PaseurCommented:
Most of what you need to know is in this article.  And you're not alone in wondering about all of this stuff - most people who are new to these things tend to overthink PHP sessions.  And when they start experimenting with edge cases, they change the standard PHP behavior... and they get bizarre results.  I would guide you to go back to the basics and then ask questions about how to achieve different effects if the basics are not what you want.  But get on a firm foundation first, before you start trying to change PHP's behavior.  In my experience, most of the changes that you can make have negative side-effects.

The PHP session is a complex thing dependent on interaction of several factors - PHP's own configuration variables, the browser expiration, HTTP cookies, garbage collection, user behavior and settings, etc.  Some programmers mistakenly think there is such a thing as a "logged-in user!"  But that is not the way the HTTP client/server protocols work.  Some of the questions you're wondering about really don't have any "why" answers - they are just the choices that PHP has made as it has grown by topsy from "Personal Home Page" to what it is today.  If we were starting over to create the language we would never do it the way it is now, and there are many things that we could improve, but that is all water under the bridge.  The session handler, flawed as it is, is actually one of the better features of the language.
http://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/

what advantage having a session name provides
I don't find any - it's a fifth wheel if you ask me.
many applications out there (usually with banks) that keep track of the session expiration
Actually, they only "sort of" keep track of session expiration, within the limits of the client/server protocol as explained in the articles above.  With some JavaScript and fiddly programming you can get it to look like there is a stateful protocol, but all of that house of cards comes tumbling down when the client changes browsers or deletes cookies, or turns off JavaScript.  It's a chain full of weak links!  And nothing we can do as programmers can strengthen the links, all we can do is program with the sure knowledge that these links will break and that our programs must take sensible decisions when the breakage occurs.
the expiration is '0', which I presume is infinite
Actually, a cookie expiration of zero is the opposite of infinite -- it's immediate and expires as soon as the browser is closed.  Notice I said "browser" and not "window," because these are different things, as explained in the E-E articles linked above.
implement a finite timed session then that brings the user back to a login after a period of time has lapsed?
You alone can't actually do that - the duration of the session is dependent on so many complex interactions that you're not really in control of the system.  You can get this effect if all of the following are true, but if any change, you may see different behaviors -- which will probably be OK and sensible for your application.

(1) set the GC percentages to 100% and
(2) the client is accepting and returning HTTP cookies and
(3) wait for the client to be inactive for the session lifetime (usually 24 minutes, an arbitrary choice by the PHP developers) and
(4) the client returns and makes an HTTP request to a session-sensitive page in the correct subdomain and
(5) your application design implements a "login" protocol as described here.

To sum up, it's not simple and there are a lot of moving parts, but they usually work well out of the box if you follow the standard protocols that PHP prescribes in the man pages.
0
elepilAuthor Commented:
Okay, I think I've beaten this dead horse enough. Even that 1440 seconds does NOT work. I intentionally left a session open before I went to bed, woke up and tried to land on a different page, and the session was still intact.

I'm a bit disenchanted how PHP, one of the oldest web scripting languages, is still so flawed after all these years.

Thank you all for your help.
0
Dave BaldwinFixer of ProblemsCommented:
You're welcome, thanks for the points.  

You're calling it flawed but it works as it was designed to do.  That's just not the way you want it to.  You probably didn't access your PHP pages over night.  That means that since the PHP interpreter was never run, garbage collection was never even checked and the session was never expired.

On a busy server serving PHP pages every second, garbage collection would probably be called several times a day.  Nothing about PHP runs in the background as 'service', the PHP interpreter Only runs when a PHP page is requested and that is the Only time that any of these things happens.
0
elepilAuthor Commented:
Hmm ... I thought sessions were handled by Apache. Isn't session management a built-in feature of Apache, and it would just be up to scripting languages like PHP, JSP, ASP, etc. to make a 'system' call to Apache to create a session?
0
Dave BaldwinFixer of ProblemsCommented:
No, I know that IIS creates sessions for all pages but it also appears that it is thru the .NET framework.  Apache does support sessions http://httpd.apache.org/docs/2.4/mod/mod_session.html  but these are not PHP sessions.  That pages says "Available in Apache 2.3 and later" and most of the hosting I use is running Apache 2.2 or older so it would not have been available.
0
Ray PaseurCommented:
Even that 1440 seconds does NOT work.
Yes it does, but just not the way you think.  That's why I wrote the articles linked above - this is not a "thing that happens," it's a permissive condition that arises and allows external things to trigger server actions after 24 minutes.  But none (or not enough) of the external things happened.  You didn't close every instance of your browser, so the browser still had the cookie and returned it.  PHP had not been active overnight, so it had not run garbage collection (servers don't do things by themselves - all they do is respond to client requests).  And so when the browser returned the cookie, PHP found the cookie and subsequently found the session data.  That is exactly how it is supposed to work.  PHP session garbage collection gets triggered based on events that did not happen in this case.  Browser cookie deletion gets triggered by events that did not happen.

You might find this article on the client-server protocols can help to give you a foundation in this stuff.  And don't rush yourself or be impatient if you don't understand all of it right away.  It's complex and detailed!
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.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.