How to prevent a started PHP session from writing? - php

I have a situation where I've started a session with:
session_id( $consistent_session_name_for_user );
session_start();
$_SESSION['key'] = $value;
but then later I decide I don't actually want to "commit" (write) this session. PHP doesn't seem to have any kind of session_abort_write() function. I don't want to destroy the session variables from prior script runs, so I can't use session_destroy()
I tried session_id(""), but that call fails. I could "redirect" the session so it writes to another session, like session_id("trash"), but that would cause a lot of PHP (Apache) connections to try to write to the same session "file", which I want to avoid.
I'm highly simplifying the problem here, we're actually storing sessions in Memcached and this is a complex codebase. So I don't want to be sending unnecessary "trash" sessions to the Memcached server all the time.

From PHP.net,
session_regenerate_id
will replace the current session id with a new one, and keep the
current session information.
session_unset will free all registered variables
session_unregister ( string $name ) will unregister a specific variable

I haven't actually determined if this method prevents writing the session to the session store, but here's the solution I finally used:
session_id( 'trash' ); // or call session_regenerate_id() as someone else suggested
$_SESSION = array(); // clear the session variables for 'trash'.
I'm hoping this has the effect that nothing will get written, but I'm guessing it still will write a blank file, because PHP can't know that sess_trash isn't already there.
If you want to completely avoid writing the session, you'll have to use a custom session handler in PHP and set a global flag to prevent writing the session.

You could probably use something with session_set_save_handler to put dummy functions in for session handling.
<?php
function fakeIt() {
return true;
}
session_set_save_handler("fakeIt", "fakeIt", "fakeIt", "fakeIt", "fakeIt", "fakeIt");

There is session_write_close(). It dumps out the session array to storage and then "closes" it - $_SESSION will still be available and read/writeable, but any changes will no longer be saved, unless you do a session_start() again later on within the script.

Related

Managing multiple PHP sessions causes script to hang under specific circumstance

Running PHP 7.2.12 on a local Apache server (XAMPP on Windows).
I'm playing around with multiple sessions in PHP to see if I can stash away an open session, play around with a new one, and retrieve the previous session. I'm about to give up and just chalk it up to some kind of file locking thing.
The code that hangs ("connection reset" in Firefox):
//first session
session_start();
$old_id = session_id();
$old_session = $_SESSION;
$id = session_create_id();
session_commit(); //same as session_write_close()
//new session
session_id($id);
session_name('new_name');
session_start();
I don't particularly need any of the code to be this way, but I'm totally lost as to why this hangs due to this:
Comment out any one of the following lines:
$old_id = session_id();
$old_session = $_SESSION;
session_name('new_name');
And it doesn't hang. You can also replace session_create_id() with an alphanumeric string literal and it won't hang. It only seems to hang when all 3 of these optional lines are present, and when using session_create_id() to create a new collision free id. Is there a way to guarantee that it won't hang?
And for anyone who has time, I have another question: What would be the proper way to stash an open session, open/manipulate/save my own session, and then restore the original session?
This works:
//previous session
session_start();
$_SESSION['var'] = 'value';
//try to stash open session
$old_id = session_id();
session_commit();
//open new session
session_id('mySession');
session_start();
//modify and save my session
$_SESSION['var'] = 'mine';
session_commit();
//restore previous session
session_id($old_id);
session_start();
echo $_SESSION['var']; //output 'value'
But I'm afraid that once I start messing with new session names in combo with session_create_id() that I'll run into the hanging problem. Maybe I should check for session id collision without the use of session_create_id()? Or should I just try to piggy-back onto the already open session?
Edit: Maybe the core of what I'm asking is that if I make a PHP class that wants to pass anonymous data to/from the client, and somebody using my class opened a PHP session prior to using my class, what's the accepted way of handling that without stepping on the previous session? Ideally I want to name my session with something unique to the class, ie. not the default 'PHPSESSID'.
You ahe handling Session wrong in first example (you call session_create_id uselessly), it probably cause to hanging. Check logs if something info was here.
Maybe problem can be exhalted when you copy $_SESSION variable to another variable and then close session. As PHP internally works it can cause to unpredictable behavion, because $_SESSION is special type of array.

PHP session_start() function: Why I need it everytime I use anything related to PHP sessions

For logging out a user from my website, I am redirecting the page to logout.php where I am using session_destroy() function. Even there also, logout functionality is not working without session_start() function. By adding session_start() function before session_destroy() function, I am able to logout the user successfully.
Why do I need to use session_start() function everytime and in every page where I am doing something related to sessions?
session_destroy() destroys the active session. If you do not initialized the session, there will be nothing to be destroyed.
Why do I need to use session_start() function everytime and in every page where I am doing something related to sessions?
So PHP knows which session to destroy. session_start() looks whether a session cookie or ID is present. Only with that information can you destroy it.
In the default configuration, PHP Sessions operate off of the hard disk. PHP asks you to explicitly tell it when you need this support to avoid unnecessary disk IO.
session_start() also tells PHP to find out if the user's session exists.
session_start() creates a session or
resumes the current one based on a
session identifier passed via a GET or
POST request, or passed via a cookie.
as per http://php.net/manual/en/function.session-start.php
Essentially by calling session_start(), PHP reads the header and cross references that session ID to what is on your system(file system/database/etc), which can then populate the $_SESSION that is relavent to that specific user. Which in turn allows you to call session_destroy() because it knows what session to actually destroy.
consider session_start() as your way of telling the php engine.... that you want to work with sessions.
and, as i understand it, always make that to be the first line ever in php page.
I was confused with the usage of session_start(); and every time I was using a session variable, I was calling session_start. Precisely, I had session_start(); more than once on each page (without even calling session_destroy()). For example,
// 1st call
session_start();
if (!isset($_SESSION['UserID']))
{
// Do something
}
else
{
// Do something else
}
// .... some other code
// 2nd call
session_start();
if (!isset($_SESSION['UserID']))
{
// Do something totally different
}
else
{
// Do something else totally different
}
This was creating a performance issue for me. So I ended up calling session_start(); just once at the very top of the page and everything seems to be working fine.
You have to call session_start once (and only once) in every file you want sessions to work in.
A common approach allowing you to only call it once is to have a dispatcher file as your index.php; call session_start in here and have this page include others based on the url's $_GET.
<?php
session_start();
if(isset($_GET['page']) && file_exists('pages/'.$_GET['page'].'.php') {
include $_GET['page'];
}
?>
//www.mysite.com/index.php?page=fish will display /pages/fish.php with session access

What if PHP sessions are already started?

I'm making somewhat of a "module" that gets included into another unrelated PHP application. In my "module" I need to use sessions. However, I get the 'session has already been started...' exception. The application that my "module" is included into is starting the session. If I cannot disable sessions in this application, what are my options? I'd like to use Zend_Session, but it seems upon first glance that it is not possible. However, maybe there is another way? Any ideas?
Thanks!
With PHP’s session implementation, there can only be one session at a time. You can use session_id to check if there currently is a session:
if (session_id() === '') {
// no current session
}
Now if there is already an active session, you could end it with session_write_close, change the session ID’s name with session_name to avoid conflicts, start your session, and restore the old session when done:
$oldName = session_name();
if (session_id() !== '') {
session_write_close();
}
session_name('APPSID');
session_start();
// your session stuff …
session_write_close();
session_name($oldName);
session_start();
The only problem with this is that PHP’s session implementation does only send the session ID of the last started session back to the client. So you would need to set the transparent session ID (try output_add_rewrite_var) and/or session cookie (see setcookie) on your own.
Try setting a custom "name" parameter for your application.
The default is PHPSESSID. You can change it to PHPSESSID_MYAPP to avoid conflicts with the other app.
Add the following code before you want to use the Session feature:
#session_start();

PHP: session isn't saving before header redirect

I have read through the php manual for this problem and it seems quite a common issue but i have yet to find a solution. I am saving sessions in a database.
My code is as follows:
// session
$_SESSION['userID'] = $user->id;
header('Location: /subdirectory/index.php');
Then at the top of index.php after the session_start(), i have var_dumped the $_SESSION global and the userID is not in there. As i said ive looked through the PHP manual (http://php.net/manual/en/function.session-write-close.php) and neither session_write_close or session_regenerate_id(true) worked for me.
Does anybody know a solution?
Edit: I have session_start() at the top of my file. When i var_dump the session global before the header redirect, i see the userID in there, but not in the other file, which is in a subdirectory of this script
I know this is an old toppic but I found the solution (for me).
I've put a exit after the header.
$_SESSION['session'] = 'this is a session';
header('location: apage.php');
exit;
This works for me
#Matt (not able to comment yet...): If:
a) It appears in the session before redirect
b) other keys work
80% of the time the problem is register_globals, and use of a equally named variable $userID somewhere (the other 19% is just overwriting in places one doesn't expect, 1% is unable to write/lock session before redirect and stale data, in which case you could try session_write_close() before the redirect). It goes without saying register_globals should be off :P
I haven't heard of this issue, but I haven't used sessions all that much.
With sessions you MUST do a few things and have a few setting setup:
cookies enabled on client side
session_start(), before anything happens
make sure you don't destroy the session(unless they want to logout)
The PHP session id must be the same (relates to cookies)
Another issue could be the $user->id is returning a reference to an object that doesn't exist on the next page. Most likely not, but make sure.
If I saw your code I could help you a lot more. But when debugging check the session key with session_id() and make sure it's the same. If you could try that then tell me I could keep helping.
I too would like to know how this ends up for when I get back into sessions.
You should start the session before using the session array.
PHP Code,
session_start();
$_SESSION['userID'] = $user->id;
header('Location: /subdirectory/index.php');
Have you got an session_start(); on the top?
Not tested but cant you do something like this:
session_start();
$_SESSION['userID'] = $user->id;
if( $_SESSION['userID'] == $user->id )
{
header('Location: /index.php');
}
I never have this Problem before, interesting
userID does not have any keyword status.
Only reason to me, is $_SESSION['userID'] is being overwritten or deleted somewhere.
Make sure you use session->start() in all the files you want to add/access the session.
One important thing ( which may not be applicable in your case ) is, if the session is being handled using cookie, cookie can be made to be accessible only under certain directory and subdirectories under that.
In your case anyhow, subdirectory will have access to the session.
Make sure both pages are the same php version
(php5, php4 sometimes have different session paths)
I had the same problem recently. I'm writting a customized MVC Website for school and, as everyone told, start_session() must be written in the very first lines of code.
My problem was THE LOCATION of "session_start()". It must be the first lines of your global controller, not the first lines of the view. $_SESSION was not accessible in controller's files because it was only initiated when the server render the view.
Then, I'm using session_write_close() after the header('location: xxx.php') call to keep session variables for the next request.
ex:
globalController.php :
//First line
session_start();
require_once('Model/Database.php');
require_once('Model/Shop/Client.php');
...
logonController.php:
...
//Users is validated and redirected.
$_SESSION['client'] = $client;
header('location: index.php');
session_write_close();
Hope it solved your problems.
This was annoying as hell but I finally figured out a solution.
config.php i had:
include 'session.php';
At the top of session.php, I had:
session_start();
By moving session_start() to the top of the config.php file, viola...
Problem solved!
Another option than killing your script forcefully with exit is to use session_write_close to force the changes to be written to the session store.
This should however not happen if your script is terminating correctly.
As the documentation about session_write_close states:
End the current session and store session data.
Session data is usually stored after your script terminated without
the need to call session_write_close(), but as session data is locked
to prevent concurrent writes only one script may operate on a session
at any time. When using framesets together with sessions you will
experience the frames loading one by one due to this locking. You can
reduce the time needed to load all the frames by ending the session as
soon as all changes to session variables are done.
In my case this only happened during debugging with Xdebug, when I triggered the same script multiple times and thus multiple process tried to manipulate the same session. Somehow the session could then no longer be unlocked.

What happens to the $_SESSION array if a PHP session times out in the middle of a request?

I have always wondered, if a PHP session times out during the middle of executing a script, will the contents of the $_SESSION array still be available until script execution ends? For example:
session_start();
if(! isset($_SESSION['name'])) {
echo 'Name is not set';
exit;
}
// imagine there is a bunch of code here and that the session times out while
// this code is being executed
echo 'Name is ', $_SESSION['name']; // will this line throw an error?
Is it practical to copy session variables to the local scope so I can read them later on in the script without having to keep checking for a session time out? Something like:
session_start();
if(isset($_SESSION['name'])) {
$name = $_SESSION['name'];
} else {
echo 'Name is not set';
exit;
}
// bunch of code here
echo 'Name is ', $name;
don't worry about such things. Nothing will happen to the session. It's initialised by sessioni_start() and $_SESSION will be always available within your script.
The default three-hour session lifetime is reset each time you open the session (see session_cache_expire), so the only way a session could time out in the middle of a request is if a request takes three hours to process. By default PHP requests time out after just 30 seconds, so there's no danger of session expiry during a request. Furthermore, the $_SESSION variable won't suddenly change in the middle of a request. It's populated when the session starts, and that's it.
The variables are copied into the $_SESSION global at the initial request, so it has the same effect as copying it to a local variable.
However, for clarity sake, it makes sense to copy it to a local variable. Especially if you plan to use the variable several times. It can be difficult to read code that has $_SESSION['variable'] all over the place.
What you needed to understand is how sessions work. A client accessing a script using a $_SESSION super global only knows the key to the session that belongs to them (Stored in Cookie/URL). This means the session data itself has nothing to do with the client. If you have the key to the session data you want to use then you can use it. Older versions of PHP had some security holes because sessions where stored somewhere that was easily accessible (I don't remember details).
Basically, if you have the session id in a PHP script you have access to that session unless the memory on the machine is flushed/harddrive is corrupt (ie Computer Restart/Device Failure).
Hope this helps, otherwise go to php.net and dive into the details on how sessions work.

Categories