PHP session values not set - php

I'm having some strange issues with PHP session variables claiming to not be set. I'm only encountering this in one particular situation:
My site has a 3-step wizard and I use sessions to store the user's selections on each step. To start the wizard, I use an init script that ensures any old wizard session data is wiped out - this init script then redirects the user to step 1. For example:
// Initialize wizard session and send user to step 1
$_SESSION['wizard'] = array();
$_SESSION['wizard']['step1'] = TRUE;
session_write_close();
header('Location: http://mysite.com/wizard/step1.php');
Then at the top of step1.php, I do a check like:
if (!isset($_SESSION['wizard']['step1']))
throw new Exception('Step1 not initialized');
When the user submits the step1 form, it is posted back to itself for validation. If it passes, another redirect is done to step 2.
Most of the time, this works fine. In fact, the init script always works and the step1 form always loads without a problem. But sometimes, after submitting the step 1 form, the 'Step1 not initialized' exception gets thrown. I don't see how the initial load could pass the check but the form post fail it moments later. Especially considering this problem happens infrequently and most of the time there are no problems at all.
I am using a database to store my session data and I don't think this is due to session timeouts or garbage collection - some related php.ini values:
session.use_cookies = 1
session.cookie_lifetime = 0
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 86400
Does anyone know what could be causing such a problem? Any insight would be greatly appreciated.
Thanks, Brian

Make sure that every script that uses your sessions begins with session_start()

If not the entire session is empty, but just that variable/key, you can use this to track the reason:
class foo extends ArrayObject{
function __destruct(){
echo 'dying:';
debug_print_backtrace();
}
}
session_start();
$_SESSION['wizard'] = new foo();
//array access is still possible
$_SESSION['wizard']['foz'] = 1234;
//reading it like an array also
echo $_SESSION['wizard']['foz'];
//on normal completion, it also gets called, the backtrace would be:
//dying:#0 foo->__destruct()
//^ ignore those
//on overwriting / deleting values, like for instance this by accident:
$_SESSION['wizard'] = array();
//the backtrace is something like:
//dying:#0 foo->__destruct() called at [filename:linenumber]
... and you'll have a filename+linenumber
Possibly write it to a temporary file rather then echo'ing it to make sure you don't miss stuff on redirects etc.

Did you remember to call session_start() before interacting with $_SESSION and also before any output has be sent to the browser (including any white space or blank lines before <?php?

Related

App using old session file after session_regenerate_id()

session_start();
$_SESSION['user_id'] = 0;
session_regenerate_id();
$_SESSION['user_id'] = 5;
After running the following code, why is my $_SESSION['user_id'] still 0 when I access it later? Am I misunderstanding how session_regenerate_id() is supposed to work? Or is it an issue that I need to address elsewhere?
I can see that two session files have been created in C:\xampp\tmp, but I don't understand why the old file is being used.
My example is me trying to understand why I could not access $_SESSION['user_id'] that I would set after running session_start and session_regenerate_id at the very beginning of my .php file:
session_start();
session_regenerate_id();
$_SESSION['user_id'] = 9; // i am unable to access this because my app is using the old file
Appreciate any help with this.
Didn't you check the session.use_trans_sid php.ini option?
In my php.ini, I have session.use_trans_sid=0 and another suggestion mentioned i do the following as well session.use_strict_mode=1. Still not working after these two edits.
Note: i assume that they are 2 different https/http calls (the two
codes starting with session_start() ... ) Can you see what all is
stored in the 2nd file in the Session before and after you do the
session_start? you can do a print_r($_SESSION) and do it before you
regenerate as well I bet there is some code in between your lines that
you haven't shared, is doing something to the session_start
I actually simplified my code down to the example in my post, and you can see it here. This way, we are not worried about any other code.
I cleared my tmp folder and ran the code. Here are the resulting files with session_regenerate_id() commented out:
First File - https://pastebin.com/mBhQCrF3
addrelease.php output is 9 for 'user_id'
I commented out the line that sets the 'user_id' to 9 to see what happens next time I log on
Second File - https://pastebin.com/QNJ6S7sY
As expected, a new file with 8 as 'user_id'
Now I will clear the tmp folder (and restart server) again and do the same with session_regenerate_id() in the code. More specifically, this is what loginuser.php will run now:
session_start();
$_SESSION['user_id'] = 8;
session_regenerate_id();
$_SESSION['user_id'] = 9;
$response['success'] = true;
$response['username'] = "test";
echo json_encode($response);
exit;
This time, since we regenerate the id, there should be two files after loginuser.php is finished. I can't tell which one was created first, but we can see that one has 'user_id' set as 9 while the other has 'user_id' at 8:
File 1: https://pastebin.com/ba1vAmjd
File 2: https://pastebin.com/H9kDfdvt
After this, the output given by addrelease.php once it's finished is 8.
With the following change to loginuser.php, we can also get an idea of what 'user_id' is before it exits and addrelease.php runs the second session_start() call:
session_start();
$_SESSION['user_id'] = 8;
session_regenerate_id();
$_SESSION['user_id'] = 10;
$response['message'] = $_SESSION['user_id'];
$response['success'] = false;
$response['username'] = "test";
echo json_encode($response);
exit;
I clear tmp folder and restart servers again. This time, 'user_id' output is 10. So we can see that loginuser.php is using the correct file, while addrelease.php does not:
File 1: https://pastebin.com/7MpRMbge
File 2: https://pastebin.com/p6RUxH8F
Hopefully I have supplied enough in response to your comment.
EDIT: Also, I don't know if this is significant, but there is a another activity (dashboard activity) between my login activity and my add release activity that does not trigger a .php file.
I think i know the core issue and have the solution as well.
From the json_encode, i assume that some frontend is querying these php files and a json response is sent. So, the session is being written to multiple times.
After writing to the session, IN EVERY FILE that you write sessions to, but PER HTTP/HTTPS request, please do an explicit session_write_close() https://www.php.net/manual/en/function.session-write-close.php .
So, what i mean is that let us assume you have frontendpage1.php that has the html for the user. If you are writing to sessions in this file, do a session_write_close() at the end. Further, if, as a result of an ajax call or something, you have file1.php, file2.php and file3.php used, where they are all writing to the session, do session_write_close() at the end of the last write of the session.
I remember reading that this good practice when sessions are written to frequently.
I had a similar issue with sessions and this worked well
Remember to do a session_start() at the start of each unique browser request/ajax request
EDIT
2nd Option: I think you have a corrupt cookie PHPSESSID . If you try with a browser that doesn't have any cookies set (for the server that is hosting your files), i bet you see the right session values.
Another way to test is, use the same browser, but just add The only thing I can think of is a corrupt cookie PHPSESSID (the default) or whatever cookie you are using, but just add session_name("myStackOverFlowID"); before session_start(); in both these files. the new session_name is not highly recommended: it is just to test.
EDIT: another option
Do the session_write_close() before regenerating the ID
Thanks
Finally, we know that an Android App is involved!
Check if any part of the App code is storing cookies, etc., in cache
Track time using hrtime(true); (recommended instead of microtime for accuracy) see https://www.php.net/manual/en/function.hrtime.php
If possible, clear out the App data on that android phone and test on a different android phone as well
So, after seeing that session was working correctly on my PC browser, I assumed from there that the issue was perhaps purely with how I set up something in my code for the Android app.
As it turns out, my CookieJar implementation was non-persistent. Using PersistentCookieJar instead, I was able to have cookies persist between my activities on the app.
So for anyone having a similar issue, I would suggest reading through this thread and if nothing works, be sure to check your cookie management implementation for the app.

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.

increment variable each time page gets called or opened?

<!doctype html>
<html>
<head>
<title>Index</title>
</head>
<form action="newquestion.php" method="post">
Question <input type="text" name="question">
<input type="submit">
</form>
<body>
</body>
</html>
PHP file...
<?php
static $q = 1;
echo $q;
$q++;
?>
I'm new in PHP. Will this not increment $q by 1 each time "newquestion.php" is called? if not how to increment this variable each time this page(newquestion.php) gets called or opened?
No, because $q resets to 1 each time the page is called. You need some sort of persistence strategy (database, writing to a text file, etc) in order to keep track of the page views.
It's also a good idea to consolidate this functionality into a class, which can be used across your code base. For example:
class VisiterCounter {
public static function incrementPageVisits($page){
/*!
* Beyond the scope of this question, but would
* probably involve updating a DB table or
* writing to a text file
*/
echo "incrementing count for ", $page;
}
}
And then in newquestion.php,
VisiterCounter::incrementPageVisits('newquestion.php');
Or, if you had a front controller that handled all of the requests in your web application:
VisiterCounter::incrementPageVisits($_SERVER['REQUEST_URI']);
Every php script inside in a page is executed when you are loading this page. So everytime your script is executes line by line. You can not count page loading number by the process you are trying.
you can follow one of the process below:
1) you can save it to the database and each time when it is loading you can execute query to increment the count value.
2) you can do it by session like this:
session_start();
if(isset($_SESSION['view']))
{
$_SESSION['view']=$_SESSION['view']+1;
}
else
{
$_SESSION['view']=1;
}
The easy way is using a SESSION or a COOKIE based persistence methodology.
Using SESSION example:
In the beggining of the page (firt line prefered) put the following code:
session_start();
Check if a session for this user has been created and recorded, if so, increment by one the value of q session variable and display it.
If not, initialize q session variable with value 1, store and display.
if(!isset($_SESSION["q"]) //check if the array index "q" exists
$_SESSION["q"] = 1; //index "q" dosen't exists, so create it with inital value (in this case: 1)
else
$_SESSION["q"]++; //index "q" exists, so increment in one its value.
$q = $_SESSION["q"]; //here you have the final value of "q" already incremented or with default value 1.
//doSomethingWith($q);
Using COOKIE example:
$q = 0; //Initialize variable q with value 0
if(isset($_COOKIE["q"])) //check if the cookie "q" exists
$q = $_COOKIE["q"]; //if so, override the q value 0 with the value in the cookie
$q++; //increment in one the q value.
setcookie("q",$q); //send a HTTP response header to the browser saving the cookie with new value
//doSomethingWith($q);
//here you have the final value of "q" already incremented or with value 1 like in session.
With cookies, you cannot use $_COOKIE["index"] = value for set a value for cookie, you must use setcookie instead for that. $_COOKIE["index"] is only for read the cookie value (if it exists).
SESSION still use cookie, but only for identify that user is the owner of that session, the user cannot change the value of session directly (only if you provide a way to they do that).
Using COOKIE the user will see a cookie with name "q" and it's value and can easily change the value through simple javascript code, browser tools (like Google Chrome Developer Console Tool) or any extension for Browser (Edit This Cookie, a Google Chrome extension that list all cookies, values and parameters for a webpage).
Remeber that any session_start call (only one per page is necessary) or setcookie calls must be made before any buffer output like (but not just) echo, print. Because both calls produces a HTTP Header "Set-Cookie" and HTTP Headers must be sent before content body, calling this methods after a buffer flushing will throw a exception.
The two examples above are per user count. If you need a per application or per page count, you must implement a custom counter system, using file system to store data (the pageviews/page requests) or database to track individuals request (with date, ip address, page url, page name, anything else).
It won't work as you think. PHP code is executed each time from start to finish - meaning that no variables are kept over from one run to the next.
To get around this, you could use a session variable (this is a special sort of variable) which will keep a value in it that you could keep for each visitor to the site. This will however work for EACH VISITOR individually.
If you want to increment the value for all users (you open the first one, it says 1, I open the second it says 2 and so on) you will need to either store it in a database (good option), write it out to a text file (not really a good option) or magic up some other way to keep it saved.
Put $q initialization in any of your init page then increment the value.
or put the variable to increment in the session. with that, you could at least see, how often one user calls your pages.
The problem with your code is that the variable is first set to 1 each and everytime the page is visited. You will have to make use of $_SESSION. But then again the problem with using session variable would be that if you are trying to increase the value of your variable from different PCs or different systems, session would not work. For this the best thing will be to insert the value in database.

Using session variable to use info on different pages

i'm having a bit of a problem. I'm trying to set up a simple webpage with only three .php pages. I want a session variable $_SESSION['userID'] to be set when a user is logged in and I want the index page to show extra info if someone is logged in.
On index.php I want to show some info, if a user is logged in I want to show some extra info.
login.php - simple log in form.
login_exe.php - takes care of database connection and verification.
So this was my idea:
On index.php, check if session is started, if not: start.
<?php
if (!isset($_SESSION)) {
session_start();
echo "session started";
}
later on, check if $_SESSION['userID'] contains a value, if so: print a string
if($_SESSION['userID'] != null){
echo "User logged in";
}
On login_exe.php i've almost the same code:
<?php
if (!isset($_SESSION)) {
session_start();
echo "session started";
}
in verification function:
$_SESSION['userID'] = $data['userID'];
header("Location: index.php");
The problem is that a new session is started on every page. How can I fix this and only start the session once? Thanks in advance
You should just put session_start() on top of documents that using sessions. Say, if you have 5 .php files that using sessions, then put 5 times the session_start() on top of them.
This is because session_start() sends headers and headers must be sent before any output (for example, any echo or whitespace).
Then, you should use something like isset($_SESSION["foo"]) and not just the entire $_SESSION array, where foo is something you set previously.
If you dont want sessions at all or need to reset the entire array, just call session_destroy() which effectively destroy the current session. Use unset($_SESSION["foo"]) when you want to get rid of a key.
Finally, you might get weird cases where you cannot read session key you write at. In these cases check what is the path of sessions and if they're writeable, or change their path:
$path = session_save_path(); // what is the path
is_writable($path); // can i write to it?
session_save_path("my/new/path"); // change the darn path;
// put -even- before session_start()!
:)
glad i help
I think the PHP manuals are really good compared to ...ahm, so just read about session_start(). It says:
session_start() creates a session or resumes the current one (...)
so all you need is session_start() very early in your code. This must be executed on every request (maybe as include).
Your code checking the userId looks fine, one important hint here: you should know exactly what isset(), empty() and the like mean in PHP, so always have the comparision of comparison at hand.
You should not ask new answers (edit: questions) in comments. Be as systematic here as you are in coding.
How to end a session:
This gives room for discussion, because there is the session cookie, which is client side, and the session data, which is server side.
I recommend:
$_SESSION = null;
Reason: this will clear all login and other associated data immediately. It leaves the cookie intact, which is normally of no concern, since all associated data is gone.

Writing to a PHP Session Variable from Ajax

Ok, this is starting to annoy me, as it's quite simply and works elsewhere, but on this current task it doesn't, so here I go!
There is a main page which relies on either a session variable being set or not to display certain information.
Let's say this page is located here: http://dev.example.com/some_page.php
e.g.
if (isset($_SESSION["some_var"])) { /* it's set so do whatever */ }
else { /* not set so do whatever else.. */ }
There is an ajax page triggered by jQuery $.ajax() to call and set this session variable to null to change the action of the main page, let's say it's located here: http://dev.example.com/ajax/some_ajax_page.php
It's code looks like so:
<?php
if (!isset($_SESSION)) session_start();
$_SESSION["some_var"] = null;
When the main page is reloaded after the ajax is triggered, the session var "some_var" is still intact, but if it's echoed after the "null" in the ajax page then it is set to "null".
Basically it doesn't seem to write to the global session, only to the local path.
Does this make sense?
Any help please? Also if you want more clarification with anything let me know!
The session_start() function will handle the attempt to create and persist a session for you, as defined by PHP's configuration, or optionally at runtime if you set your own save handler. Make sure you read the documentation here:
http://us2.php.net/manual/en/function.session-start.php
For your code, you want to make sure to call session_start() at the beginning of any page in which you'd like to save or access session variables. So your page above may look like:
<?php
session_start();
$_SESSION['myvar'] = 'some value';
Then in a different page you can try to access that value:
<?php
session_start();
if ($_SESSION['myvar'] == 'some value') {
// do something
}
That should work fine.
Get rid of the check for session. If this is the only file your calling just do this:
<?php
session_start();
$_SESSION["some_var"] = null;
Also, are you using framework that auto-regenerates session ID on each request? If so, you'll might have problems.
If you have a dev machine to play with and permissions to do so, you can manually delete all sessions in the /var/lib/php/session/ directory. As you use your site, only one session file should be created. You can also inspect that file to see what is getting written and when.
Seems that you are using different sessions vars. One for the AJAX call and another for the normal pages calls. This may occur when you do not init both call in the same way (or using the same starting code that initializes the sessions)
Be sure to session_start() both calls using the same session_id.
// try in both calls
session_start();
echo session_id(); // must return the same id in both calls
Why don't you use unset? It is the proper way to do it.
Turns out the application I was working on had it's own session_handler and if it was not included before requesting the session data, it was always invalid, eventhough it was the same session_id.

Categories