Background:
I am trying to write a script that connects on a regular basis to a web server and checks if some information on a specific page was changed. I already got this working using a combination of bash (for scripting), curl (for the actual connection) and crontab (for the scheduling).
Since the server requires authentication, I first used curl to do a POST request on the login page with my credentials and saved the cookie file (containing the PHPSESSID). Now i can use the cookie file when doing the request for the actual web page I want to check.
Question(s):
When does the server actually clear the PHPSESSID i set with my first request? I imagine it must do this sometime, otherwise it would crash because it keeps storing information about every single session that was ever started.
If the PHPSESSID is cleared on closing the browser is there some way i can simulate that even using curl?
It's a little more complicated than just "when it's cleared"
A session has a lifetime in PHP. The default is 24 minutes. That means that after you connect to a website, your session is valid until
You close the browser (which won't be simulated with cURL unless you just drop the cookies)
OR
24 minutes pass
Each time you load a page and the server calls session_start() that expiration time will be bumped an additional 24 minutes (technically speaking it's actually bumped 24 minutes at the end of the script execution on pages where session_start() is called).
When that cookie actually expires, your session is no longer valid, and $_SESSION will be empty on the server side. But your data is still on the server until the next time that the server performs a session garbage collection cycle to clear out expired sessions which, depending on the session handler in use on the server, may or may not actually delete your data. A bank, for example, might send the data off to an archive server in case they ever need the records.
The server removes the session after the session timeout-time has passed after the last request. This is by default 1440 seconds (24 minutes), it can be changed in php.ini file.
The session is not flushed serverside on closing the browser, the client loses his session data though, since the browser deletes his local memory of the session. But if you keep your sessionid somewhere safe you can use it later on again, if you stay within the timeout frame of course.
This is exactly how session hijackings work, they get your sessionid in some way and can then set this sessionid on their own machine and continue your session.
Related
I'm trying to implement a system to keep an user logged in for a while. I can do that by using cookies and storing it into database and then identifying him.
But recently I heard a session can be alive even when user closes his browser and opens a new window. I mean can a session still be available after closing/opening the browser again (or even multiple time)?
How much time (maximum) can I use $_SESSION["LoginValidation"] in following script?
<?php
session_start();
$_SESSION["LoginValidation"] = ture;
Currently that session will be available until closing the browser.
In order to make the session persist after closing the browser you need to set an expiry time for the session cookie. A cookie without an expiry time is deleted when the browser is closed, and is normally referred to as a session cookie (which is not the same thing as a PHP session - just related).
(side note: if your browser is configured to "save open tabs" at exit, then the session cookies may be saved by the browser even though they should be deleted)
So you could just set session.cookie_lifetime to a large value. But that doesn't stop the session data stored on your server from being deleted - to keep the data for longer you need to up the value for session.gc_maxlifetime.
BUT THIS IS THE WRONG WAY TO FIX THE PROBLEM
There are security and capacity implications to implementing such persistent sessions - you should certainly NEVER implement this as default behaviour - only where the user has explicitly given their consent.
Using a "Remember me" cookie as a sort of lightweight session system is the best practice solution. Give it a random value (suggest you use a reasonably reliable source of random numbers, e.g. base64_encode(openssl_random_pseudo_bytes(64)) and a name which does not conflict with other cookies, and store it along with the data you really want to persist across the actual sessions (e.g. authenticaticated username).
Approach 1) session.cookie-lifetime : This is the lifetime of the cookie, which by default is 0, which means the cookie is destroyed when the browser is closed. You can set a longer lifetime by increasing this variable.
It is relative to the server time, so you need to account for differences in the time in your clients' machine and your server's.
There's also session.gc-maxlifetime, which is the time after which the session data is seen as garbage in the storage and is destroyed.
While you can set these settings both to relatively high values and have it working, I would recommend against doing so, as this will leave a lot of unnecessary session data hanging around in your session storage, due to the GC not collecting actual dead session
Or
another approach is for session to make alive even after closing of browser save session in db and get its id , and set that id in user cookie via
setcookie("name","value",time()+$int);
so you can fetch that value from $_COOKIE["name"]; use it to get session variables from data base
My questions:
session.gc_maxlifetime in php.ini: Does the session.gc_maxlifetime start from the session_start() point or the latest request to the server? (Assuming I have a few requests without a session_start() being called.)
What is the best practice to use the $_SESSION object so as to not waste precious RAM (automatically clear idle sessions in time)? Or is this something that happens automatically by the time mentioned in session.gc_maxlifetime?
How do I correctly check if a session has expired (as against a session which never got created)? Or are both the same? isset($_SESSION['any_variable']) === FALSE
Assuming I don't have control over php.ini, how do I increase session.gc_maxlifetime?
session_start(): If a session has "timed out", calling session_start will always start a session with the previous variables unavailable(a brand new session). Is that correct?
Good question! I would assume that the default filesystem session handler would go off last access but not all filesystems support an atime timestamp. I'll see what I can find out on that front.
Sessions are by default stored as files on disc. They only take memory when loaded. Unless you've built a custom session handler that stores sessions in a RAM disc or in a memcache server or similar, or unless you're storing a huge amount of state in the user's session I doubt memory use will be a major concern.
When session_start() is called the previous session data is loaded into PHP. If the session has expired then there will be no session data to load and a new empty session will be created. So yeah, if you check for the existence of a variable in $_SESSION that you're expecting to always be there then you can use that to determine if the user's session has expired (but only after session_start() was called).
Simply set gc_max_lifetime to how long you want sessions to last in seconds. 600 is 10 minutes, 86400 is one day, etc.
Yes (with some caveats, see below).
There are a few things you need to be aware of with sessions though. First is that there's two components to a session: A server side state record that holds all the data stored in the session, and a client side token that PHP uses to associate a particular user with a particular state record. Normally the client side token is a cookie. Cookies have their own expiration date, so it's possible that the session can expire before the session state is due to do so. In that case the user will stop sending the token and the session state is effectively lost. If you're adjusting how long a session lasts you need to set both the server side state expiration time and the client side cookie expiration time.
As for stale state, the session garbage collection system doesn't always run every time session_start() is called. If it was the overhead would be crippling to a big PHP site with a lot of sessions. There are configuration options that specify the probability that the GC will run on any given invocation of session_start (I believes it defaults to 1%). If it doesn't run then a stale session record may still be treated as valid and used to populate $_SESSION. It probably won't have a serious effect on your system but it's something you need to bear in mind.
I need to close a session when the browser is closed, when it crashes, when a PC restarts, and so on.
I know there is cookie solution, but I need something secure, server side, because the user can delete the cookie.
You dont have to. The garbage collector will clean up your sessions.
The php ini setting session.gc_maxlifetime determins how long a session can remain active.
When this value is exceeded the session is automatically removed.
This can not be done the way you imagine it.
You can not directly react to such an event in php.
The closest you can get is using ajax to keep the session alive.
Create a small php script which does nothing but update $_SESSION['last_request'] lets call it pulse.php
Insert a javascript in you pages which sends a request to
yourdomain.com/api/pulse.php every 60 seconds.
Check if the last request uis older than 70 seconds on every request
if it is start your clean up script and kill the session.
If the browser crashes your cleanup script will not run. The session will timeout the usual way unless you get a request after more than 70 seconds but before the session expires.
You can fix this if you store the session data in a database.
Then you can run a worker or a cronjob which regularly checks if there are sessions where the last request was more than 70 seconds ago.
Why 70 seconds? If you expect a request once per minute you should allow some time for klatencys or slow hardware on the client side.
Hi You don't need to close session. because its default behavior of session that it destroy the session when user close the browser. And we can alter this behavior by changing lifetime of session in php.ini file by doing
session.cookie_lifetime = 0. Otherwise by default
when you reopen the browser there will be no data in session.
cookie delete automatic when user run crashed brouser.
in php no way to know when user close brouser.
some not easy way it's websocket and long poling connections, but it's not easy to configuration and not good idea.
I thought that sessions were stored on the client side because of the session getting deleted when the browser closes. However, today I've been told that this is not true and that the session is stored on the server.
So how does a session know when a browser was closed, so that the session gets deleted?
It doesn't. There are two factors at play:
the lifetime of the cookie on the client-side;
This cookie contains the session ID. It does not have anything to do with the session data itself.
The manual probably doesn't stress this enough:
This has nothing to do with lifetime of a session
Whatever you set this setting to, it won't change how long sessions
live on your server.
This only changes HTTP cache expiration time (Expires: and
Cache-Control: max-age headers), which advise browser for how long it
can keep pages cached in user's cache without having to reload them
from the server.
the lifetime of the session data on the server-side;
The session is "activated" via a lookup with the session ID from the client. Its lifetime is controlled via session garbage collection settings discussed here.
A commenter posted on the session.cache_expire documentation page, presumably actually talking about the session data:
What most people also don't know, is that most Linux distributions
(Debian and Ubuntu for me atleast) have a cronbjob that cleans up your
session dir using the value set in the global /etc/php5/php.ini (which
defaults to 24mins). So even if you set a value larger in your
scripts, the cronbjob will still cleanup sessions using the global
value.
If you run into that situation, you can set the global value higher in
/etc/php5/php.ini, disable the cronjob or even better, do your own
session cleanup in a non-systemwide directory or a database.
As you can see, confusing abounds amongst the community when making the distinction between session tracking and session data storage.
Session is identified by a cookie, which does get stored in the browser. It can have an expiry date/time, or it can be set to expire when the browser is closed. When the cookie expires, you can't identify your session storage any more, and the session is effectively expired. It does not get deleted unless the system admins or programmers specifically make a cleanup.
EDIT Just noticed the PHP tag. For how PHP cleans up its session files, check this question.
The server has no way of knowing when the browser is closed.
Closing the browser will delete the session ID cookie from the client.
The session is deleted from the server once there are no requests in a given amount of time (the session timeout).
I understand that a session cookie can be given a lifetime (session.cookie_lifetime) and that after that lifetime the cookie expires regardless of whether a user interacts with the site.
I would therefore assume to set this to 0 to indicate they should stay live until the browser closes.
I also think I understand that the garbage collection lifetime (session.gc_maxlifetime) can be set for a cookie and that as long as a user does not exceed this time between their clicks then the cookie will remain active.
To test this out I've been trying to get a 10 second session timeout.
I tried:
ini_set('session.gc_maxlifetime',10);
but the session doesn't timeout after 1 minute at least.
Is this because I am only saying to the garbage collector that the session has a life of 10 seconds but I'm not actually triggering the garbage collector?
How do you set the garbage collector going or does it just run every time a session is requested?
First of all, don't confuse cookie settings (which are client-side) and garbage collection (which is server-side). Cookie settings only affect the expiration of the session_id. Session data may still exist on the server even if the browser has removed the cookie and, on the contrary, the server can remove the data while the session_id is still remembered by the browser.
The cookie can be set to expire when you close the browser or in a specific date and time (I believe the default option is the first one, but I'd have to check it). In both cases, if the user interacts with the site the cookie will remain valid since it's renewed on each response.
Session data is removed when the garbage collection is launched but you must take into account that:
The garbage collection is started randomly, triggered by a page request.
It removes session data not modified in more that gc_maxlifetime seconds.
By default, session data is stored in files and PHP doesn't track what site owns what files. That means that storing sessions in the default shared location makes you lose control on session expiration: the site that's configured to keep session data for the shortest time is likely to remove data from other sites with longer time.
To sum up, if you want full control on your data lifetime you need to store session data in a private directory, e.g.:
session_save_path('/home/foo/sessions');
ini_set('session.gc_maxlifetime', 3*60*60); // 3 hours
ini_set('session.use_only_cookies', TRUE);
session_start();
The server has a default timeout set in it's INI files, if not overridden from within a script. In apache it is set from within PHP.ini i believe. You also need to enable the garbage collection function, which I believe is also set in php.ini.