Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this PHP script (called by AJAX) randomly not load SESSION correctly?

Ahoy StackOverflow,

I have come across this issue in my project: in short, from what I've gathered, is that the PHP script called via AJAX is not properly registering SESSION variables that were set at the top of the index.php page. At first, I assumed that it was due to session locking, so I went ahead and added session_write_close(), however, that didn't fix the issue.

This issue only occurs about 25% percent of the time after a new user session begins (ie: when a user logs in).

I went ahead and deleted 90% of the code to get the bug down to its bare minimum coding necessary to reproduce.

Bad result from Firebug via ajax.php

image

Expected result from Firebug via ajax.php

image2

Note: Both results show the return of index's print_r($_SESSION) as Array ( [userid] => 3724 [trialstatus] => 1 [trialtcompletions] => 0 [userlevel] => 5 ) which lets me know the issue isn't with the session being set on the index page.

Does anyone know a fix (perhaps not even code-wise, maybe even a server setting) that will properly allow the script called via AJAX to access the Session variable correctly?

Testing Scenario for Reproduction

  1. Delete all cookies for domain
  2. Load page (max 2 times). Issue never occurs after 2 reloads.
  3. If bad result isn't shown, repeat steps.

index.php

<?php

if (session_status() === PHP_SESSION_NONE) session_start();

if (!isset($_SESSION['userid']))
{
    $_SESSION['userid'] = 3724; //$login['AccountID'];
}

$_SESSION['trialstatus'] = "12";
$_SESSION['trialtcompletions'] = "12";
$_SESSION['userlevel'] = "12";
session_write_close();

print_r($_SESSION);
?>
<!DOCTYPE html><html><head><script src="./js/jquery.min.js"></script>
<script>
    function loadStage(step,input,callback){
        $.ajax({
            type: "POST",
            url: "./ajax.php",
            data: { step: step, input: input },
            dataType: "JSON",
            timeout: 5000,
            success: function(data){
                if(data !== false){
                    callback(data);
                }
            }
        });
    }

    $(document).ready(function(){
        startLoadingSequence();
    });

    function startLoadingSequence(skipped){
        loadStage(1,skipped,function(data){});
    }
</script>
</head></html>

ajax.php

<?php
if (session_status() === PHP_SESSION_NONE) session_start();

print_r($_SESSION);

if (!isset($_SESSION['userid']))
{
    die(json_encode(array(
        "error",
        "You must be logged in to view report data."
    )));
}
?>

Per request:

phpinfo

Read comments for extra information

like image 706
TurdPile Avatar asked Jul 03 '15 01:07

TurdPile


2 Answers

Two things can cause this issue.

  1. You don't have enough space in session save path (df -h) or you server don't have permission to save it.
  2. Your server is behind a load balancer, and you must save sessions in a persistent backend like memcache or redis.
like image 115
Jordi Martín Avatar answered Oct 22 '22 15:10

Jordi Martín


If you're running a load balancer then you have to make sure your servers are hitting a common point for data. By default PHP stores sessions in the local file system. That becomes a problem if your load balancer sends you from server A to server B, where that file doesn't exist. You could set up a network share and make sure all web servers use that share. So you could create an NFS share and then add session_save_path or set it within php.ini

session_save_path('/your/nfs/share/here');

Another option is to write your own session handler that puts sessions into your database. You could then use something like memcached to store the sessions in a way that you won't hammer your DB every time you read your session data.

like image 8
Machavity Avatar answered Oct 22 '22 16:10

Machavity