PHP header redirect with nested folders - php

I have a nested folder structure and I want to do a header redirect to login.php from every page that is not authorized. (Every page will include security.php)
NOTE: This whole folder could be in a subfolder so doing DOMAIN + login.php won't work.
Example:
-index.php
-login.php
-security.php
-people.php
-activities
- view.php <-- How can I have do a header redirect back to login.php from here
security.php
if (!isAllowed())
{
header("Location: login.php");
}
index.php
require_once('security.php') // Works fine
activities/view.php
require_once ('../security.php'); //Works fine, but the HEADER redirect doesn't work

activities/view.php ->
require_once ('../security.php');
the ../ indicates that you move a folder back.

There's a lot of things you can do. I'd recommend setting a constant to define the current path and then use that to create an absolute link. You could also use server header data to figure out your current path and decide what the destination is based on that. Also, in php5+ use
require_once 'security.php';
Instead of ()

In my experience, by far the best approach is to define a useful include_path for the application.
In php.ini, we'd set our path like so:
include_path = ".:/path/to/webroot/your_app/includes"
...and then, in our application, include any contents of that directory with a simple include 'file.php';. This abstracts all that ugly path stuff out of our application and leaves the logic clean. We can also make it easy to reuse code across applications:
include_path = ".:/path/to/webroot/your_app/includes:/path/to/shared/includes"
If you do not have access to your php.ini, you can use PHP's set_include_path function. This approach also improves portability.

Updated this post according to the asker's update:
header('Location: /login.php'); should work.

Related

PHP: Problems redirecting relative paths with header()

I am doing a project with XAMPP from my university in which they ask me to use the header function to perform redirects and a file structure to follow. But I'm having some problems.
I have the following file structure:
backend/validateSession.php
backend/show.php
index.php
login.html
So, validateSession.php has this inside:
session_start();
if(!isset($_SESSION["DNI"])){
$path = "./login.html";
header("location: ".$path);
}
And both index.php and show.php have to include validateSession.php
index.php:
include_once "./backend/validateSession.php";
show.php:
include_once "./validateSession.php";
When entering index.php, validateSession.php correctly redirects me to login.html
But if I enter from show.php, I have an error because the path is ./login.html instead of ../login.html
So my question is: How could I solve this problem if index.php and show.php need different paths so that header can redirect me correctly? Thanks in advance.
EDIT: header should redirect me to localhost/prog/TP/login.html, but
if i use this path in the header, it probably won't work if someone else tries to access it from their own XAMPP.
The path for an HTTP redirect is relative to the domain, not to the filesystem (since the browser knows nothing about that). In this case, you should just be able to use
$path = "/login.html";
header("location: ".$path);
Note the lack of . at the start of path. domain.com/index.php, domain.com/backend/show.php (and any others) will all redirect to domain.com/login.html

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?

Fix a redirect loop?

I have the following code in my index.php page:
<?php include("/includes/widgets.php") ?>
And in my widgets.php page:
<?php
header("Location: /");
?>
What I want to achieve with this is to redirect it if the user visits it, but allow it for including.
But I get the following error:
The webpage has a redirect loop
How can I fix/prevent the redirect loop, but still redirect the user and not the server.
Place the widgets.php file in a folder not accessible to HTTP clients. I.e on apache webserver, either put it above your document root (into it's parent) or use .htaccess file to block users from it.
e.g.
deny from all
I think I know what you need :)
Change code index file to next
define("IS_INDEX", true);
include("/includes/widgets.php"
Change code for widgets.php to next
if (!defined("IS_INDEX")) {
header("Location: /");
exit();
}
The issue is you are redirecting back to the same page, which then redirect again, and again, and again.
An easy fix would be to wrap the redirect in an if, and only redirect if they aren't already on the index page; but this is just patching what looks like an architectural problem.
Something like:
if (ltrim($_SERVER['REQUEST_URI'], '/') != 'index.php')
header('Location: index.php');
One way is to check if __FILE__, which is the file loaded, regardless of included or not matches up with the file requested which is in $_SERVER['REQUEST_URI'] (or $_SERVER['PHP_SELF']).
I use this on our development site in a page that is usually included to get the output as debugging.
if(basename($_SERVER['PHP_SELF'])===basename(__FILE__)){
//do some debugging
}
Typically you wouldn't use basename, but this is on a non-public facing development site and the file has a pretty unique name so I'm not worried about the file being included with another file with the same name or anything.
One possible way is to add a parameter to the redirection, e.g.
if (!$_REQUEST['redirect'])
header("Location: /ìndex.php?redirect=1");
That way redirection can happen only once.
Another way is to stop redirection if the user already is on the /. I´d suggest to combine both.

php authentication best practice...?

I have a simple login page that checks credentials against database and then every page includes auth.php that verifies $_SESSION['logged'] is set and that session isn't expired.
Problem is that every page also includes another page tab.php (something like a menu), which I also need to restrict access to, but including auth.php inside tab.php makes the inclusion occur twice. If I don't include the auth.php in tab.php, though, anyone can access tab.php directly bypassing authentication check and possibly retrieve private information.
Any best practice to solve this situation?
EDIT:
And I forgot to ask, but what path you use to make it relative to site root? As both auth.php and tab.php are in folder and the index.php which includes tab.php is in root - the include function gives an error for either index.php or tab.php according to what path I use ('./includes/auth.php' OR './auth.php') - If you know what I mean. I tried '/includes/auth.php' but that doesn't work.
Use include_once instead of include in your files (or require_once and require). This will insure that your auth.php file will only be included once in the lifetime of the script.
include_once and require_once will definitely assure that you don't have the same file included more than once (at the same time make sure you're authenticated).
What I would do, however, is add your includes in a "include" folder and forbid access - to people who would type in the path manually - through an htaccess file. This way you could keep your includes in one place (whatever your header includes might look like) and keep your include files clean and still out of reach. If you were to do this you'd only have to do what Jan. mentioned in the answer above and check if your $_SESSION['logged'] is set (and whatever other checks you need)
Just check in tab.php if the session is initialized and $_SESSION['logged'] is true. This will work fine, if auth.php is loaded first.
What about using require_once("auth.php");? This makes sure, that auth.php is included (otherwise application will stop) but only includes the file once which seems to be your goal.
Try include_once(). See ( http://php.net/manual/en/function.include-once.php )

Categories