PHP: Sessions across includes - php

I am needing to use sessions for my php page, so, on my index.php page, I add session_start(); right after the opening php tag.
But, this page has some includes, inside of which have other includes. So, deeper down, when I want to call a $_SESSION var, it is not working.
How can I access a session var even deep down into .inc files?

session_start() works across includes. Your problem must be somewhere else:
#file1.php
var_dump($_SESSION['somevar']);
#base.php
session_start();
include 'file1.php';
//the contents of $_SESSION['somevar'] will be dumped

Related

PHP Session Authentication of Directory Index

The context:
I'm building a PHP 7 web application, it uses a PHP session to login and check to see if the user is logged in on each page. Here is the basic makeup of most pages:
<?php session_start(); ?>
<?php include 'the_header_and_menu.php'; ?>
<p>Page content</p>
<?php include 'the_footer.php'; ?>
At the top of the_header_and_menu.php file is an include to session_check.php which is located outside the site's directory. This PHP process does five checks, the most basic one included below.
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] == 'false') { // If loggedin is not set, or is false, then run this block.
header('Location: http://example.com/index?eject=noLogin'); // Send the user to the eject page.
die(); // Exit the process.
}
Process summary: User logs in, which creates a session and its variables. When the user loads a page, a session check is performed to make sure that the user's account is valid and authorised. If the account or session is no longer valid/authorised, then the user is redirected to the login page (index).
The issue: When someone who's not logged in enters http://example.com/dashboard, they are ejected using the first check (featured above). However, if they enter http://example.com/process/, the checks seem to count for nothing and the user is shown the page. This page does not just include a directory listing, but calls the http://example.com/process/index.php file to represent it instead.
The question: How can I apply the same logic that protects individual pages like dashboard.php, to the case of protecting directory indexes?
Own answer:
The issue here was one which was simple, but overlooked.
At the top of the_header_and_menu.php file is an include to session_check.php which is located outside the site's directory.
Within the header and menu file was the session check include. However, because the session check was located outside the main directory (like much of the back-end), I had referenced to it through a relative path, similar to the one below.
include_once '../mainfolder/php/subfolder/sessioncheck.php';
However, because the file was being included to a subdirectory, it should've included a further ../ operator.
include_once '../../safe/php/users/sessioncheck.php';
The solution: Instead of performing a session check through the header and menu, I am now including it on every page I want to protect. This is by no means a perfect solution and simply acts to get things working again.
Thank you to Daniel Schmidt, who got me looking in the right direction!
Directory indexes don't usually come from PHP - they are served by your webserver (nginx, apache, ..). Today, there is obviously no need to have that indexes enabled.
It looks like you're not sending each request to you're PHP process(es). I tend to suggest checking your webserver configuration.
The issue here was one which was simple, but overlooked.
At the top of the_header_and_menu.php file is an include to session_check.php which is located outside the site's directory.
Within the header and menu file was the session check include. However, because the session check was located outside the main directory (like much of the back-end), I had referenced to it through a relative path, similar to the one below.
include_once '../mainfolder/php/subfolder/sessioncheck.php';
However, because the file was being included to a subdirectory, it should've included a further ../ operator.
include_once '../../safe/php/users/sessioncheck.php';
The solution: Instead of performing a session check through the header and menu, I am now including it on every page I want to protect. This is by no means a perfect solution and simply acts to get things working again.

Include php file that includes another php file?

My PhP files contain some long string constants and I'm trying to factor them out. So I created "my_string_constants.php" and used include in header.php. So far that works fine.
Now another file, page.php also requires the string constants and header.php. The scheme below tries to clarify these dependendies.
The string constants now seem available in my header only, not the rest of my page. I tried to resolve this by adding global ... to each string constant in string_constants.php. This resolved the error of "Unknown variable" but my string constants still seem unavailable to most of the page content.
What's the right way to get this working?
UPDATE
The issue's been solved. I should have used define(myString instead of $myString = .... By doing so, I need just one include in header.php and the constants will be available to page.php as well.
Thanks a million, you guys are great.
One thing you would want to do is distinguish a constant from a variable. Especially if other developers end up working on this, they will be confused by your terminology.
For constants, you do not need to declare them as global and they are defined like so:
define('MY_CONSTANT', 'Value');
It seems to me that the constants file is acting as your site wide configuration file, so to me, it makes sense to have that on every page, regardless of whether header is used or not. I would normally create a bootstrap file for this purpose.
bootstrap.php:
<?php
require_once(__DIR__ . '/constants.php');
require_once(__DIR__ . '/database.php');
require_once(__DIR__ . '/session.php');
You get the point, then every accessible page needs to include this bootstrap file and then possibly the header.
page.php:
<?php
require_once(__DIR__ . '/bootstrap/bootstrap.php');
require_once(__DIR__ . '/header.php');
?>
<h1>Page Title</h1>
In header.php, since it requires these constants, you can handle this in two ways, either check that the constants are defined (meaning, bootstrap was included first) or just use another require_once to make sure that file was loaded.
if (!defined('MY_CONSTANT')) exit('Bootstrap failure');
or
require_once(__DIR__ . '/bootstrap/constants.php');
Going to many directories or "files" deep regarding includes can really cause issues later when you are trying to debug. As a rule I try to only go one level deep in regards to including files. I.e. Create a folder called includes and place everything in there. If there is a file that needs multiple variables, functions etc, then include them in the needed pages at that point doing several includes like so:
<?php
include("includes/header.php");
includes("includes/functions.php");
?>
There are also other issues in regards to having multiple includes, like if you have sessions or cookies some LAMP stacks will require you to declare
session_start();
at the top of every page including all included php files that may need access to that session or cookie.
So to answer your question I believe the simplest solution would be to re-organize your site or script.
in the header page ontop u write
include 'header.php';
and in header.php you write
include 'my_string_constants.php';
so in this case the page.php calls the header and in the header the my_string_constants is being called...is this what you mean?

How to disable direct entry to a html?

Say I have two html files called html1 and html2. html1 contains an embedded swf file.
Now what I want is that the user can not go to html2 directly via url. He has to click it through the link in the swf in html1. Is there a way to achieve this?
If not possible in html, is it possible with php?
Thanks
EDIT:
After answer from John, I went ahead and tried his advice, but I can never access the file2.php, even if I have been to file1.php before. It keeps redirecting me back to file1.php, even when it should not.
My code from file1.php
//file1.php
<?php
session_start();
$_SESSION['enableAccessTill']=strtotime("+5 minutes");
?>
Here is file2.php
//file2.php
<?php
session_start();
if(!isset($_SESSION['enableAccessTil'])||$_SESSION['enableAccessTil']<time())
{
header("Location: indexFLA.php");
exit;
}
?>
what am I possibly doing wrong?
found it, it was due to a misspelling - "enableAccessTil" and "enableAccessTill"
professional solution:
create protected directory and make .htaccess file in directory and copy all embedded and partial files into directory.
this directory not accessible whit get url.
but you can include file whit php include and require method.
.htaccess content:
deny from all
This wont be possible in just plain html.
An easy way to do this is php is by setting a session variable in file 1, and test in file 2 it the users has been to file 1.
file1:
<?php
session_start();
$_SESSION['enableAccessTill'] = strtotime("+5 minutes"); //set the time here till when the user has access
[...]
file2
<?php
session_start();
if(!isset( $_SESSION['enableAccessTill'] ) || $_SESSION['enableAccessTill'] < time() ){ //If time is expired
header("Location: file1.php"); //redirect user to the first file
exit;
}
[...] //continue your script here.
Things with referrer check do usually fail (some browsers/firewalls blocking that variable).
Based on the options you described, it would sound most reasonable to make the html2 a php script and check that the referrer is the html1 file. The script should display the normal html1 content if that is the case, or an error message otherwise.
A sneaky user could still get around this if they knew what was going on, but it should be fine for the majority of your audience.
Possible with php.
At index.php you must write
<?php
define('START', true);
include 'file.php';
At file.php need write
<?php defined('START) or die('Direct access!!'); ?>
<embed> your swf file embed
This way you will prevent direct access
You could do it with PHP by using session variables. Start the session in html1. Check for the session in html2. If it exists, display html2. If it does not, don't display html2. In either case, destroy the session in html2.
well is posible with html you has two options one is cookies and the other is local storage in html5
localStorage.hasClick = true;
alert(localStorage.hasClick);
http://www.html5rocks.com/en/features/storage
but obviously the straightforward solution is php / c# / ruby / etc...
//when I said html i refer to use only client side html/javascript

php session_start with include files

i learned a lot about session start from my previous question. Now i'm wondering how session locking occurs when files are included in other files. Lets say i have:
page.php
include('header.php');
...some html content....
include('sub_page.php');
...more html....
header.php:
session_start();
..save session vars...
..print web page header...
sub_page.php
session_start();
...use session vars....
..print page content...
When i open page.php, does the session become unlocked as soon as header.php is done? or is it live for the whole page.php life, so sub_page's session is blocked? Is the session_start in sub_page necessary? Would it be better practice if I session_write_close every time i'm done with session data? (Though that would mean session_starting everytime i'd like to use a session variable).
You should start session only one time. In your example, just need session_start() at the first line of page.php
session_start() will generate E_NOTICE if session was previously started. You can use #session_start() to ignore it.
It also generates E_NOTICE if you use session_start() after you output HTML code.
I would recommend creating a session.php file that you would include once, at the first line of each page. That way, the session is handled in ONE file, in case you need to change validation or session settings (and don't need to worry about your question).
Due to the answers above talking about errors if session already started, I just wanted to point out you can do:
if (!isset($_SESSION))
{
session_start();
}
Then if the $_SESSION is already started (set) it wont perform the start function.
Although there's nothing better than a well structured file and folder layout with a good framework setup. Even if just a simple framework structure which separates business logic from presentation.
This way, you'd have something similar to a config folder with initialisation scripts, or at the very least have include files in some folder which are included in all pages/scripts.
Then you simply have your session_start() in (depending on your setup) either the very first include file, or in a separate include file and then include that session file when needed in a specific area of the script.
Either way, you then don't need to call it in any other files, as you know it's simply not required based on your design structure.
If you do not have a file which is always included, then at least use the isset() check.
As of PHP 4.3.3, calling session_start() after the session was previously started will result in an error of level E_NOTICE. Also, the second session start will simply be ignored.
As long as you are not accessing or creating session variables you do not need to worry about session_start(). You only really need to worry about session_start if the script you are running will create session variables, or relies on accessing session variables to function.
If file1 is not accessing or creating variables for use by other scripts then don't call it. If file2 that is included by file1 is creating or relies on variables in the session then file2 should call session_start(). File2 will be included in the session and will be able to access all session variables, but file1 will not.
If you call session_start() in file1, then file2 will be able to access all session vars as if it called session_start().
Hope this clarifies the situation a bit more.
Great tip from James re using isset. This will prevent attempting a pointless session call.
Also check your php.ini file for the session.auto_start var. If this is set to 1 then all files will be run as if they made a session_start() call. Set it to 0 in the php.ini file if you want to control it yourself.

$_SESSION wont work without filename in URL?

I'm currently working on a site where I'm trying to make use of the session variables.
I have a controller script (index.php) that begins with session_start(); and has two different HTML files included within if statements. Everything works all groovy when I go to /quote/index.php, the session variables that I've set are echoed on the page as expected, however if I remove 'index.php*' from the URL so it points to just /quote the page loads however none of the session variables show up.
I'm not using session_destroy anywhere in my scripts and the session variables aren't echoing '0' so I'm fairly sure they aren't being unset, it seems as though they are just ignored without the filename in the URL!
Any insight as to why this is occuring would be awesome,
Thanks
/quote/index.php (with extraneous bits removed):
<?php
session_start();
if (isset($_GET['form']))
{
include 'form.html.php';
exit();
}
if (isset($_GET['fetchquote']))
{
$width = mysqli_real_escape_string($link, $_POST['width']);
$height = mysqli_real_escape_string($link, $_POST['height']);
$_SESSION['height'] = $height;
$_SESSION['width'] = $width;
}
include 'quote.html.php';
?>
The session variables are echoed in quote.html.php
what are the two file names?
seems that one of the file that you are including is named index.html and resides in the mysite.com/quote/ itself. And if I am not wrong, if in a directory there are index.html and index.php then the index.html is loaded by default unless the file is explicitly specified in the url. So it seems in your case when you are not specifying the index.php explicitly,the index.html is being loaded.Of course this is the case only if there is an index.html there in the directory.
Make sure you are also using session_start() at the top of the PHP pages where you want to echo the session variable. And make sure index.php is the only index in your root.
You are checking if an option is set via the GET method. Where is your form using the GET method?
Post your entire script and you'll get much better answers.
This has probably something to do with the validity scope of the session ID cookie. Because if the cookie path is set to /quote/, the cookie will only be available in /quote/ and beyond.

Categories