PHP Session: check without starting one - php

Is it possible to check if a certain session ID exists without starting a new one?
The reasons I'm asking this are:
If every user not logged in visiting the site requires session_start(), soon the session folder will be bloated with unnecessary files (even with garbage collector cleaning up expired sessions).
Of course this can be mitigated by destroying the sessions of such users. However, in this case, it seems there would be an overhead of creating and destroying files (unless PHP is smart enough to cancel these operations). Is this a bad practice?
If the user is just a guest and doesn't require a session, there is no need to create one for him.
Ideal Solutions:
if( session_exist($_COOKIE['PHPSESSID']) )
{
session_start();
}
Or:
session_start(RESUME_ONLY);
Follow-up
There is a PHP package that explains much better the aforementioned issue. Briefly, some interesting excerpts are:
Resuming A Session
[...]
You could start a new session yourself to repopulate $_SESSION, but that will incur a performance overhead if you don't actually need the session data. Similarly, there may be no need to start a session when there was no session previously (and thus no data to repopulate into $_SESSION). What we need is a way to start a session if one was started previously, but avoid starting a session if none was started previously.
[...]
If the cookie is not present, it will not start a session, and return to the calling code. This avoids starting a session when there is no $_SESSION data to be populated.
Source: Aura.Auth
Notes:
This question was initially posted as Checking for PHP session without starting one?.
However, IMO, none of the answers addressed properly the issue.

I think you are trying to solve the wrong problem here. To answer your question, no, you must use session_start before preforming session operations. You could also destroy the session if it isn't needed in the same request with session_destroy.
You can work around the session_start problem with some clever session storage options, but I think that is just the wrong answer to the problem you have. The size of sessions stored on the FS is really negligible when your servers installation footprint is at least 8GB. Furthermore, the default session storage location is /tmp which is commonly setup as a ramfs to avoid any disk overhead. If you are running into the limitations of FS session storage, you probably need to use a different SessionHandler like memcached, not worrying about if you need to start a session. On a related note, stop prematurely optimizing your code. Session storage is not going to be an issue until you need more than one server. In reality there are going to be many more database queries that would benefit from an additional index than obscure optimizations like this one.

Related

Is there some kind of performance (or other) punishment for using session_start() but not really using the session super-array?

I've always wondered why PHP makes you manually session_start() in order to gain access to the immensely useful $_SESSION "super-array".
It strikes me that this might be causing a lot of stress on the server, but not really make a difference in practice unless you have an extreme amount of users.
I don't really see why it would cause such a strain, though, if you don't use that array/mechanism. And if you do, you always want session_start() to have been called... It would really be nice to finally get this straightened out.
The manual doesn't offer any explanation: https://www.php.net/session_start
It's not really a question of how much overhead it causes, as far as why sessions aren't started by default. There are tons of possible PHP applications that have nothing to do with session variables (including any CLI use!), and therefore, on principle it shouldn't be automatically started. Establishing an idle database connection ("immensely useful!") also doesn't create silly overhead. It's still not done by default. Resources should be available, but uninstantiated.
The main performance impact caused by starting a session, with or without ever using it, basically involves (quoting from the manual on session_start()):
PHP will call the open and read session save handlers. ... The read callback will retrieve any existing session data (stored in a special serialized format) and will be unserialized and used to automatically populate the $_SESSION superglobal when the read callback returns the saved session data back to PHP session handling.
This typically means disk access to look up and read the serialized session data. Even if it's empty or non-existent. (It will not be created until $_SESSION variables are used; but you won't know if it's there without trying!) Also: your session ID is typically stored in a cookie. Want session? Make a cookie, take a cookie, pass a cookie, read a cookie, etc. pass/read on each page load. Unnecessary baking and trading, and we'd rather avoid redundant HTTP traffic.
Aside that, there's a strange and wonderful thing called session locking that can make you scractczch your head a lot and wonder why you can't load long-running scripts on your site in two tabs simultaneously, even when you've double-damned-configured your Apache, MySQL and the rest to handle concurrent connections and/or space alien armadas on steroids. Without session locking, you could. (Alas, debugging long-running scripts with sessions on!)
Significantly, this will haunt you with concurrent AJAX requests to PHP scripts with sessions; they'll be sequentially processed instead. There are ways to overcome session locking delays, but the default behavior blocks parallel execution, and requests are queued, and it's rather annoying but a necessary evil to prevent race conditions and session corruption (read more).
So much for the obvious performance/quirks side. In terms of customizing how things work, there are functions that may be called before session_start(), such as session_name() (for named sessions). The session_start function itself (as of PHP 7) takes an optional array of session parameters which you couldn't use, were the session started by default.
If you look at the link above, you'll notice that there is in fact a session auto-start option in php.ini session configuration:
session.auto_start boolean
session.auto_start specifies whether the session module starts a session automatically on request startup. Defaults to 0 (disabled).
There are some related cautions in PHP Intro to Sessions on the auto_start option:
Caution If you turn on session.auto_start then the only way to put objects into your sessions is to load its class definition using auto_prepend_file in which you load the class definition else you will have to serialize() your object and unserialize() it afterwards.
If you are certain that you always want to use sessions, the simplest move would be to create a bootup file that you require at the beginning of files that use sessions; add the path to the file into your include path; and then simply <?php require 'sessions.php' before your main code begins.
The session bootup file could also have some of your own session-handling functions, etc. relevant standard material. This route would give you more freedom than the auto-start option, plus a way to implement other options and functionality across all your session-using code. You shouldn't rely on the auto-start in any case, in case you ever want to create code that can be easily deployed into environments with default PHP configuration!

Handling session_regenerate_id() in ajax requests

I want to secure a little bit my application, especially I want to improve the way how sessions are handled. So, at this moment I know several facts:
session_regenerate_id(false) does not destroy old session
session_regenerate_id(true) destroys old session. With ordinary page reloads there is nothing wrong with using session_regenerate_id(true).
However when making dozens concurrent AJAX requests there may be a
problem which results in an error message object destruction failed.
So, there is nothing left to do, then to use
session_regenerate_id(false) in AJAX request.
But what is needed, is to somehow mark previous outdated sessions, which become outdated as a result of invoking session_regenerate_id(false), as "zombie" sessions that will somehow be destroyed and not litter the sessions folder.
I need some practical advice on how to implement this.
All session cleanup, including those with regenerated IDs, is handled by PHP's session garbage collector. There is nothing special needed when calling session_regenerate_id(false) to remove old sessions from storage.
PHP's settings for session.gc_probability, session.gc_divisor, and session.gc_maxlifetime apply.
You can also run your own session storage cleanup based on last access time.

how to not create empty sessions for guest visitors

I'm using a CMS-framework that initates session_start() upon page creation, however 90% of the site visitors are guests without the need for sessions, resulting in an awful lot of empty session-variables at server.
What's the best practice here? IF logged in, I need to know at an early level so I guess it means is both:
Postpone session_start() until it's actually needed
Keep the session_start() at an early stage, but make it conditional based on existance of cookie PHPSESS
Or is there a better fix, unknown to I?
Many large sites postpone the session initialization until it's actually needed, e.g. on cart pages and the user profile screen of each user.
In theory this isn't that complicated, if you were using a config file which would be required within all pages you could simply swap out a different config file for the pages that don't require any user recognition.
You're using a CMS-framework so perhaps you're somewhat limited within it. If you can differentiate the page creation process, using session_start(); in one case and not in the other, then this shouldn't be that big of a deal. Keeping the logged in users logged on once returned to the other area of the system (the index file etc) would not work though. Of course you could be using local_storage to aid you with that but relying on JavaScript only isn't very reliable.
The easiest way would probably be to spit the system into two areas, one which doesn't use any sessions (index, other information files, etc) so the process behind those page creations would be different, i.e. not using sessions.
Perhaps you could have a session class like mentioned but it would most likely conflict with other previously outputs causing the sessions to fail, but if you could flush the other output then this could possibly work, but it's kind of a hack in my opinion and it wouldn't really solve the previously mentioned problem.
Have you considered changing the lifetime of the sessions? The default setting is 24 minutes but would reducing it to 15 change anything? Is 24 minutes really that big of a deal for you? Maybe the settings in your environment make them be even longer. Are there other aspects of the system that might be the actual performance issue? Are you hosting the system yourself or do those empty sessions really not matter?
If you're expecting a lot of guest traffic without the need for sessions, then don't use it unless you absolutely need it. What I typically do is create a class for session, and add the session_start to the constructor of the class. Then, when I need sessions, I can simply call the session class within an underlying global.class.

CodeIgniter session library - potentially dangerous behavior?

According to the documentation (http://ellislab.com/codeigniter/user-guide/libraries/sessions.html), the CodeIgniter session library has the following behavior:
"When a page is loaded, the session class will check to see if valid session data exists in the user's session cookie. If sessions data does not exist (or if it has expired) a new session will be created and saved in the cookie. If a session does exist, its information will be updated and the cookie will be updated. With each update, the session_id will be regenerated."
I think this behavior can be dangerous from a security point of view, because somebody could flood the site with requests and that way pollute the session store (which, in my case, is a mysql database). And my app is running on an ordinary web host..
Is there any easy solution to this which does not require too much additional coding? Maybe a library that could substitute for the one that ships with the core? I don't want to code it all myself because I think that would defend the purpose of using a framework.. and I actually don't want to use another PHP framework, since, for my specific requirements, CI is perfect as regards the freedom it gives you...
because somebody could flood the site with requests and that way pollute the session store
So? Then you just have a bunch of sessions in the db. This doesn't affect the validity of sessions. If there is a mechanism to delete old session based on space/time, then those sessions are gone and the former owners of those sessions will need to re-authenticate.
If you are worried about collisions, do a little research and you will find that any collision probability is a function of the underlying operating system and/or PHP itself, so CodeIgniter can't help you there.
Also, maybe disk space fills up but that is an operations/architecture problem, not a CodeIgniter problem and not a security issue in and of itself.

How can i know if a session is still active or not?

I'm storing the sessions ids in a database table. I
want to run a script that reads from the table every
session id and check if this session is active or not.
I know that session information is stored in a
directory (/tmp by default) and removed from there
when the session is closed. But if the user close his
browser without disconnecting from the session the
session file is still in the /tmp directory.
How can I know if a session is still active or not?
I have searched the session functions and didn't find
anything that could help.
Generally speaking, the only way is to have a "last used" datetime/timestamp which you update every time the session is referenced, and discard/deactivate sessions after they haven't been used for a certain amount of time.
It's not possible to tell if a session will be referenced further as they're not kept open between requests, simply referenced when needed ... and need is dictated by the ever fickle client.
If your sessions are file based, as it sounds, you can use the last accessed date of the individual files, possibly save yourself a bit of trouble.
If you are keeping sessions in the database. Add a last accessed or modified timestamp to the database table. I've put code in my procedures that retrieve or store session information that DELETE FROM sessions WHERE modified is more than an hour ago. However long you want your session to be. At every call you can update that timestamp. It seems that would cause a performance hit, but I've used that pattern/process quite a bit. I almost always use the database to store session information. You should research session_set_save_handler(). I can try to gather some of my own code from previous project where I utilized this, but I'm sure that reading the manual on this and googling implementations will help you quite a bit.
Why would you care about this already outdated sessions? They will be cleared from temporary folder in some random time anyway.
You should check last access time in your database and if it's more then some predefined timeout - mark it as dead.
But think about your performance too. It's a way better approach to store your session data in memcache or something similar to it - just store it in memory, not in DB. Read more about it here: http://memcached.org/
It's really easy to store your session data in memcached: http://www.dotdeb.org/2008/08/25/storing-your-php-sessions-using-memcached/
There isn't such a function.
PHP itself use somewhat an hack to determine when a session is expired, there are several
options into the php.ini configuration file.
In short, every time a session started there is a gc_probability/gc_divisor chanche that php will start a
garbage collection of pending data.
The session accessed before gc_maxlifetime seconds are considered expired and PHP deletes them.
You can relay on this behaviour tuning the envolved options or mimic this behaviour with a
similar approach.
For reference:
http://it.php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime
http://it.php.net/manual/en/session.configuration.php#ini.session.gc-probability
http://it.php.net/manual/en/session.configuration.php#ini.session.gc-divisor

Categories