My code is dropping all PHP sessions after logging - php

Once my users log in and verify themselves I am sending my adimninstrators to an activity page. This inital page shows session values when I dump the sessions. However when I move to any other page in my site I lose the session values.
I am setting my pages by including the classes in the header file. I calling session start (if (session_id() === "") { session_start(); }) at the top of each file in the site. I have nothing within my code that will cause my session to be destroyed.
when the user is being authenticated, i am using this snippet of PHP
<?php require_once('includes/init.php'); ?>
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset($_POST['login'])) {
require 'auth_login.php';
} elseif (isset($_POST['register'])) {
require 'register.php';
}
}
?>
when they submit the form, they are sent to auth_login, and the successful login/verification code looks like this:
if ($_POST['code'] == $users->auth_code) {
$_SESSION['logged_in'] = 'true';
$_SESSION['id'] = $users->id;
redirect("/admin/activity.php");
}
This is the content of my init file:
if (session_id() === "") { session_start(); }
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once("functions.php");
require_once("config.php");
require_once("database.php");
require_once("db_object.php");
My functions file:
<?php
function classAutoLoader($class){
$class = strtolower($class);
$the_path = "includes/{$class}.php";
if(is_file($the_path) && !class_exists($class)){
require_once($the_path);
} else {
die ("File, {$class} does not exist");
}
}
spl_autoload_register('classAutoLoader');
function redirect($location){
header("Location:{$location}");
}
?>
My config file:
<?php
define('DB_HOST', 'XXX');
define('DB_USER', 'XXX');
define('DB_PASS', 'XXX');
define('DB_NAME', 'XXX');
?>
My database class
class Database{
public $connection;
function __construct(){
$this->open_db_connection();
}
public function open_db_connection(){
$this->connection = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if ($this->connection->connect_errno){
die("Database connection failed ". $this->connection->connect_errno);
}
}
public function query($sql){
$result = $this->connection->query($sql);
$this->confirm_query($result);
return $result;
}
private function confirm_query($result){
if (!$result){
die("Query Failed". $this->connection->error);
}
}
public function escape_string($string){
$escaped_string = $this->connection->real_escape_string($string);
return $escaped_string;
}
public function the_insert_id(){
return $this->connection->insert_id;
}
}
$database = new Database();
When my user lands on activity.php, i am using these 2 snippets
echo '<pre>';
var_dump(session_status());
echo '</pre>';
echo '<pre>';
var_dump($_SESSION);
echo '</pre>';
There I get my 2 values in the session dump and I get int(2) session status. When i hit any other page in my directory I lose the sessions in the dump, but i still see a int(2) for my status.
I am leaning towards thinking that my issue exist within the htaccess file.
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/(admin|processes|paypal-ipn/)$
RewriteRule ^.*$ ./index.php
All traffic except a directory is having the file extensions striped. Could that be what is causing my problem.
Thanks in advance.

Work In Progress:
I'm afraid I'm going to have to go, but we have proven that the session saves correctly and can be read from the same file, as is written to. So if the other files are in another folder then there may be some folder specific PHP.ini settings messing up the session reading? I think the issue does appear to be outside the scope of what you've put in your question, but that is not to place blame, simply that it's more complex to establish what's going on.
I have nothing within my code that will cause my session to be destroyed.
Then this means that sessions are not being started, so the session data is unavailable to PHP.
I do have session start at the top of my init file.
So the next step is to var_dump($_SESSION); immediately after you start the session, like so:
session_start();
error_reporting(E_ALL);
ini_set('display_errors', 1);
var_dump($_SESSION);
require_once("functions.php");
...
And let us know what this outputs? Are the sessions empty or are they full of stuff at the point of time the page loads?
I do not know how to access the sessions directory on my server
You need to load the phpinfo or the php.ini file and see where it says:
session.savepath . This is where sessions are stored. Once you know this you can open that folder, and find the session file, usually sess_<session_id value> and see if any data is being written to the session.
Update 3:
Please try this adjusted code:
if ($_POST['code'] == $users->auth_code) {
$_SESSION['logged_in'] = 'true';
$_SESSION['id'] = $users->id;
session_write_close();
session_start();
error_log(print_r($_SESSION,true));
redirect("/admin/activity.php");
This will write to the session, close the session and then open the session and save the contents to the Error Log file. You should be using error logs far more than screen displays.
Result:
The error log shows me this. [02-Aug-2019 21:10:50 UTC] Array ( [logged_in] => true [id] => 1 ) [02-Aug-2019 21:10:50 UTC] PHP Notice: Undefined index: email in /home/linepickleadmin/public_html/admin/auth_verify.php on line 34

Related

Replacement for Session['msg'] if I used session_start twice? Error: Session has already been started

I get an error above my students.php
A session had already been started - ignoring session_start() in ...
I have a CRUD wherein I have to notify user if the students have been updated, deleted or created.
The CRUD is working fine, however, if I remove session_start() in server.php, the notification wouldn't show.
students.php:
<?php if (isset($_SESSION['msg'])): ?>
<div class="msg">
<?php
echo $_SESSION['msg'];
unset($_SESSION['msg']);
?>
server.php
if(!isset($_SESSION))
{
session_start();
}
...
$_SESSION['msg'] = "New student saved";
header('location: students.php'); //redirect back to page
$_SESSION['msg'] = "Information updated";
header('location: students.php'); //redirect back to page
redirect.php
<?php
session_start();
if (!isset($_SESSION['username']))
{
header('location: login.php');
die();
}
?>
Should I just change the var $_SESSION['msg'] to another variable? I'm a total beginner in PHP, sorry if it might be a stupid question.
It doesn't look like you have a framework going, so I think there are some general tips to help your script succeed.
1) Have a top-level config file in your site root that you include at the top of all your MAIN pages:
/config.php
<?php
# Create some helpful constants
define('ROOT_DIR',__DIR__);
define('DS',DIRECTORY_SEPARATOR);
define('FUNCTIONS',ROOT_DIR.DS.'functions');
define('BASE_URL','http://www.example.com');
# This includes our function loader (see below)
include_once(FUNCTIONS.DS.'loadFunc.php');
# Load the getSession() function (see below)
loadFunc('getSession');
# Start session here
session_start();
2) Then create some helpful functions (I would learn Object Oriented Programming instead so you can use a framework effectively, but functions are better than nothing):
/functions/loadFunc.php
function loadFunc($name)
{
if(!is_array($name))
$name = array($name);
foreach($name as $func) {
# If the function is already loaded, skip
if(function_exists($func))
continue;
# See if the function file exists
if(is_file($file = FUNCTIONS.DS.$func.'.php'))
include_once($file);
}
}
}
/functions/getSession.php
function getSession($key=false,$clear=false)
{
# If requesting a specific value return that
if(!empty($key)) {
# Get value
$value = (isset($_SESSION[$key]))? $_SESSON[$key] : false;
# If the key is set and clear is set, clear the value
if(isset($_SESSON[$key]) && $clear) {
unset($_SESSON[$key]);
}
# Return session value
return $value;
}
# No key set, return full session
return $_SESSION;
}
/functions/setSession.php
function setSession($key,$value)
{
$_SESSION[$key] = $value;
}
/functions/redirect.php
function redirect($to,$exit=true)
{
header("Location: {$to}");
# You should exit on redirect
if($exit)
exit;
}
3) Now, when you go to create a page, you include this config ONCE at the top of the page:
/students.php
<?php
# Now that you include this, you know session is always set
include(__DIR__.DIRECTORY_SEPARATOR.'config.php');
# Get the key msg from the session and use parameter #2 to clear the session key
$msg = getSession('msg',true);
# It's not empty, write message
if($msg): ?>
<div class="msg">
<?php echo $msg ?>
</div>
<?php endif ?>
/server.php
<?php
# Include config
include(__DIR__.DIRECTORY_SEPARATOR.'config.php');
# Load our two required functions
loadFunc(array('setSession','redirect'));
# You have to determine either message here, not both.
# Using pseudo-code here to demonstrate
if($add) {
# Use function to set session value
setSession('msg',"New student saved");
}
elseif($update) {
setSession('msg',"Information updated");
}
# Since both use the same redirect, you only need it once
redirect('students.php');
So, if you delete all your session_start() in all your files except for the config and then always include the config on the top-level page at the top, you won't run into errors for the session.

What is wrong with php configuration?

This is simple php code with sessions:
<?php
session_start();
function testSession() {
//global $_SESSION;
var_dump($_SESSION['test']);
}
if (!isset($_SESSION['test'])) {
echo " Nope";
$_SESSION['test'] = " Yeap";
} else {
testSession();
}
?>
The problem is that "$_SESSION" is not a superglobal. "$_SESSION" is undefined in testSession function scope, it is visible only in the main scope. If I uncomment "global $_SESSION" than all will work.
upd:
The error is "Undefined variable: _SESSION" at line var_dump($_SESSION['test']);
upd:
if you write this code:
<?php
session_start();
if (!isset($_SESSION['test'])) {
echo " Nope";
$_SESSION['test'] = " Yeap";
} else {
var_dump($_SESSION['test']);
}
?>
all will work correctly.
Always put your session_start(); at the start of the page.
Try using:
<?php
session_start();
echo "Session test ";
function testSession() {
//global $_SESSION;
var_dump($_SESSION['test']);
}
if (!isset($_SESSION['test'])) {
echo " Nope";
$_SESSION['test'] = " Yeap";
} else {
testSession();
}
?>
Make sure session_start(); is called before any sessions are being called. So a safe bet would be to put it at the beginning of your page, immediately after the opening <?php tag before anything else. Also ensure there are no whitespaces/tabs before the opening <?php tag.
After the header redirect, end the current script using exit(); (Others have also suggested session_write_close(); and session_regenerate_id(true), you can try those as well, but I'd use exit();).
Make sure cookies are enabled in the browser you are using to test it on.
Ensure register_globals is off, you can check this on the php.ini file and also using phpinfo(). Refer to this as to how to turn it off.
Make sure you didn't delete or empty the session.
Make sure the key in your $_SESSION superglobal array is not overwritten anywhere.
Make sure you redirect to the same domain. So redirecting from a www.yourdomain.com to yourdomain.com doesn't carry the session forward.
Make sure your file extension is .php (it happens!).
Session variables not working php

PHP $_SESSION variables are not being passed between pages

I am working on a school project where I need my .php pages communicating. I have header.php where I set connection to the database and start the session. In order to start the session only once, I've used this:
if(session_id() == '') {
session_start();
}
PHP version is PHP 5.3.10-1 ubuntu3.18 with Suhosin-Patch (cli)
I am trying to pass some $_SESSION variables between pages, but they keep being unset when I try to use them on a page that doesn't set them.
I see many people have complained about this, but I still can't find the solution.
login-form.php
<?php
if (isset($_SESSION["login-error"])) {
echo '<p>'.$_SESSION["login-error"].'</p>';
}
?>
login.php
$_SESSION["login-error"]= "Username or password incorrect";
There is a code snippet of what is not working for me.
Thanks
You can try this.
In your function file put this
function is_session_started()
{
if ( php_sapi_name() !== 'cli' ) {
if ( version_compare(phpversion(), '5.4.0', '>=') ) {
return session_status() === PHP_SESSION_ACTIVE ? TRUE : FALSE;
} else {
return session_id() === '' ? FALSE : TRUE;
}
}
return FALSE;
}
Then you can run this in every page you want session started
if ( is_session_started() === FALSE ) session_start();
With this I think you should be good to go on starting your session across pages. Next is to ensure you set a session to a value. If you are not sure what is unsetting your sessions you can try var_dump($_SESSION) at different parts of your code so you be sure at what point it resets then know how to deal with it.
The variables are probable not set, because you haven't activate the session variables with session_start().
session_id() == '' is not a correct conditional . Use instead:
if (!isset($_SESSION)) { session_start();}
if you have session started then you can set a session variable
if (!isset($_SESSION["login-error"])) { $_SESSION["login-error"]= "Username or password incorrect";}
Before you call $_SESSION["login-error"], type session_start(), just for testing, to find when the session signal is missing. You said
PHP $_SESSION variables are not being passed between pages
session_start() and SESSION variables needs to be included at the beginning of EVERY page or at the place where SESSION variables are being called (through a common file, bootstrap, config or sth) at the beginning of EVERY page. ie the command to read those data from the server is needed.
Since my header.php file included "connection.php" file, I put
session_start();
at the beginning of connection.php and deleted it from header.php file. Now it works fine. Thanks all for your help!
PHP sessions rely on components of HTTP, like Cookies and GET variables, which are clearly not available when you're calling a script via the CLI. You could try faking entries in the PHP superglobals, but that is wholly inadvisable. Instead, implement a basic cache yourself.
<?php
class MyCache implements ArrayAccess {
protected $cacheDir, $cacheKey, $cacheFile, $cache;
public function __construct($cacheDir, $cacheKey) {
if( ! is_dir($cacheDir) ) { throw new Exception('Cache directory does not exist: '.$cacheDir); }
$this->cacheDir = $cacheDir;
$this->cacheKey = $cacheKey;
$this->cacheFile = $this->cacheDir . md5($this->cacheKey) . '.cache';
// get the cache if there already is one
if( file_exists($this->cacheFile) ) {
$this->cache = unserialize(file_get_contents($this->cacheFile));
} else {
$this->cache = [];
}
}
// save the cache when the object is destructed
public function __destruct() {
file_put_contents($this->cacheFile, serialize($this->cache));
}
// ArrayAccess functions
public function offsetExists($offset) { return isset($this->cache[$offset]); }
public function offsetGet($offset) { return $this->cache[$offset]; }
public function offsetSet($offset, $value) { $this->cache[$offset] = $value; }
public function offsetUnset($offset) { unset($this->cache[$offset]); }
}
$username = exec('whoami');
$c = new MyCache('./cache/', $username);
if( isset($c['foo']) ) {
printf("Foo is: %s\n", $c['foo']);
} else {
$c['foo'] = md5(rand());
printf("Set Foo to %s", $c['foo']);
}
Example runs:
# php cache.php
Set Foo to e4be2bd956fd81f3c78b621c2f4bed47
# php cache.php
Foo is: e4be2bd956fd81f3c78b621c2f4bed47
This is pretty much all PHP's sessions do, except a random cache key is generated [aka PHPSESSID] and is set as a cookie, and the cache directory is session.save_path from php.ini.

PHP Cannot delete this cookie if my life depended on it

I am creating a simple Logout script and my cookie ("is_logged_in"), for some reason, cannot be deleted, despite all of my efforts.
I have tried all of the following (+ lots more):
setcookie("is_logged_in");
setcookie("is_logged_in","");
setcookie("is_logged_in","",time()-3600);
setcookie("is_logged_in","",time()-3600,"\");
setcookie("is_logged_in",FALSE); # or NULL, 0, etc.
unset($_COOKIE["is_logged_in"]);
Here is my PHP code (and yes there is a session_start() but it just isn't included in this excerpt).
<?php
require_once $_SERVER["DOCUMENT_ROOT"]."/taxi/support/required_classes.php";
ob_start();
class Logout {
final public function __construct(){
$_SESSION = array();
if(isset($_COOKIE["is_logged_in"])) {
setcookie("is_logged_in","",time()-3600,"/");
} // end if
session_destroy();
header("location: ../pages/index.php");
} // end __construct
} // end class Logout
$_logout = new Logout();
ob_flush();
?>

In my PHP + Ajax code, why does $_SESSION disappear during execution?

I'm working on a simple Ajax exercise where I separate the query, the Ajax, and the url that Ajax calls. In short, I run a query in one page and attach the resulting array to $_SESSION, then I display some html and the Ajax code calls a third page to get the elements from the array one by one via a counter attached to the $_GET superglobal. The three files are linked by require_once().
When the page loads initially, all is as expected. The $_SESSION contains the entire array pulled from MySQL, and the $_GET is null.
Once I click on the button to execute the Ajax code, the $_GET value changes and receives the value of the counter, as expected.
However, $_SESSION ceases to exist. The var_dump now returns null and I get an error Notice: Undefined variable: _SESSION in C:\wamp\www\.....\ajax.php. I don't understand why that is.
Here is my code. First, index.php :
<?php
session_start();
$dbhost = "localhost";
$dbuser = "admin";
$dbpass = "XXXXXXX";
$dbname = "test";
mysql_connect($dbhost, $dbuser, $dbpass);
mysql_select_db($dbname) or die(mysql_error());
$query = "SELECT ae_name FROM ajax_example";
$qry_result = mysql_query($query) or die(mysql_error());
$result;
while($row = mysql_fetch_array($qry_result,MYSQL_ASSOC)){
$result[]=$row;
}
$_SESSION['array']=$result;
require_once ("viewUsers.php");
require_once ("ajax.php");
?>
Then the html and ajax code in viewUsers.php:
<html>
<body>
<script type="text/javascript">
<!--
function createRequest() {
try {
request = new XMLHttpRequest();
} catch (tryMS) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (otherMS) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = null;
}
}
}
return request;
}
var indx=0;
function calcIndex(){
return indx++;
}
function ajax(){
ajaxRequest = createRequest();
var index=calcIndex();
var url="ajax.php?index=" + index;
ajaxRequest.open("GET",url, true);
ajaxRequest.onreadystatechange = display;
ajaxRequest.send(null);
}
function display(){
if(ajaxRequest.readyState == 4){
var ajaxDisplay = document.getElementById('ajaxDiv');
ajaxDisplay.innerHTML = ajaxRequest.responseText;
}
}
//-->
</script>
<form name='myForm'>
<input type='button' onclick='ajax()' value='Show next name' />
</form>
<div id='ajaxDiv'>Your result will be displayed here</div>
</body>
</html>
And then the PHP that receives the array from $_SESSION and (should) return the next item based on the value of $_GET['index']. The file is ajax.php.
<?php
var_dump('Get value in ajax.php',$_GET); // The values are as expected
var_dump('Session value in ajax.php',$_SESSION); // This global cease to exist after I click the button
if(isset($_SESSION['array'])){
$array=$_SESSION['array'];
$cnt=count($array);
$index=null;
if(isset($_GET['index'])){
$index=$_GET['index'];
if($index>=$cnt){
$str="And that's it....";
}else{
$str="The next name is ".$array[$index]['ae_name'];
}
echo $str;
}
}
?>
The problem is that session in ajax.php is not started / resumed.
When you call index.php, it is:
index.php -> .. -> ajax.php (SESSION EXISTS (session_start() called in index.php))
then you request your ajax.php through ajax:
html -> ajax.php (SESSION DOESNT EXISTS (session_start() was not ever called as we dont come from index.php))
You just need to initialize / resume session in your ajax.php, but you have to check if its not already initialized from index.php. Put this chunk of code into your ajax.php file:
if(!session_id()) // check if we have session_start() called
session_start(); // if not, call it
ajax.php needs a session_start() at the beginning, otherwise, when you call it standalone via ajax, you won't have a session, hence no $_SESSION var.
From PHP DOC
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.
When session_start() is called or when a session auto starts, PHP will call the open and read session save handlers. These will either be a built-in save handler provided by default or by PHP extensions (such as SQLite or Memcached); or can be custom handler as defined by session_set_save_handler(). 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.
Without calling session_start definitely $_SESSION would not be populated accordingly why advice is to always call session_start if you in your script if you are going to be using sessions .
Quick Few steps
Remove require_once ("ajax.php"); from index.php its not needed there
PHP CODE
$_SESSION['array']=$result;
require_once ("viewUsers.php");
require_once ("ajax.php"); //<------ remove this
Add session_start(); to ajax.php
From PHP DOC on mysql_query
Use of this extension is discouraged. Instead, the MySQLi or PDO_MySQL extension should be used. See also MySQL: choosing an API guide and related FAQ for more information. Alternatives to this function include:mysqli_query()
PDO::query()
Your index.php should finally look like this
session_start();
// Put this in config file
$dbhost = "localhost";
$dbuser = "admin";
$dbpass = "XXXXXXX";
$dbname = "test";
$array = array();
//Start DB Connection
$mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname);
$query = "SELECT ae_name FROM ajax_example";
$result = $mysqli->query($query);
//Get Information
while ( $row = $result->fetch_assoc() ) {
$array[] = $row;
}
$result->free();
$mysqli->close();
// Add Info to session
$_SESSION['array'] = $array;
require_once ("viewUsers.php");
#JDelage,
Your question has a very simple solution - Just add session_start() at the top of the ajax.php file.
However, the major problem here is lack of organization in your code structure.
Session / Configurations are preloaded in most of the actions. And these are included in a file which is loaded in every call.
Your file ajax.php apparently seems to be an independent file, however is dependent upon index.php, meanwhile index.php depends on ajax.php (require_once).
So the best work around for your type of code is as follows.
bootstrap.php
<?php
// just to check to prevent overwriting of your configs / preloads.
if(!defined("INITIALIZED")){
session_start();
//.. some other basic settings if you require
define("INITIALIZED", 1);
}
?>
index.php
<?php
include_once "bootstrap.php";
// .. your code
require_once("viewUsers.php");
require_once("ajax.php");
ajax.php (Yes you need session_start() here, because when you make asynchronous request to this file, it acts as an independent request regardless of index.php. AJAX call is a client side asynchronous request, not a server side. )
<?php
include_once 'bootstrap.php';
// .. your code
viewUsers.php
// since your viewUsers.php file isn't an independent file and is included by index.php only, you can simply add this line at the top to prevent direct invocation of the file.
<?php
if(!defined("INITIALIZED")){die();}
PS:
There isn't an unique solution. An approach is what you have to decide. Your approach is an approach, which isn't any kind of approach. Rest is fine.
I hope I have answered your queries.
Regards,
You have a number of if conditions that are making it difficult for you to see errors. Add some echo statements at those locations to see what is happening in your program flow. It will be easier to troubleshoot. For example:
<?php
//session_start();
echo 'You sent ' . $_GET['index'] . '<br>'; //Ensure index value arriving
if(isset($_SESSION['array'])){
$array=$_SESSION['array'];
$cnt=count($array);
$index=null;
if(isset($_GET['index'])){
$index=$_GET['index'];
echo 'Got to here<br>'; //Another checkpoint - send something back
if($index>=$cnt){
$str="And that's it....";
}else{
$str="The next name is ".$array[$index]['ae_name'];
}
echo $str;
}else{
echo 'GET var "index" was not set<br>';
}
}else{
echo 'SESSION var "array" was not set<br>';
}
?>
Of course, you will remove those echo statements as you fix your code... They are only temporary, for debugging.
I faced similar issue. I found that in one of the ajax call I forgot to call session_start().
when I ensured that I session_start() is always called in all the php code that are called thru ajax, then this problem went away.
When using AJAX sometimes the session is not carried over. In your AJAX post/get include the sessionID. Then on the receiving end do something like:
$sid = ($_POST['sid']) ? $_POST['sid'] : ''; //Check for posted session ID
session_start($sid); //Start session using posted ID or start new session
*Old-school method, yes, but tried and true.

Categories