PHP protects the directory from direct URL access

I have an ADMIN script.

admin/index.php

      

All activity is done through this index.php

file.
Users register before accessing the program's functionality.
$_SESSION['user_authenticated']

is created and set to true .

admin/template/..

      

This folder contains files images

, css

, javascript

.
They are used only within this ADMIN. (backend only)

Question:

I need all the contents of a directory admin/template/..

to be protected from direct access .
It should only be accessible to authenticated users.

I'm guessing there should be .htaccess

requests redirecting to check_session_auth_variable.php

which looks if $_SESSION['user_authenticated']

is true or false and redirects to the requested file or throws a 404 error ?

I know that the best option would be to place the directory outside of the website root, but in my case I need to keep the directory structure as it is, unchanged.

+3


source to share


3 answers


admin / .htaccess:

RewriteCond %{REQUEST_FILENAME} !check_auth.php
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .* check_auth.php?file=$0 [QSA,L] # pass everything thru php

      



admin / check _auth.php:

$file = $_GET['file'];
if($_SESSION['user_authenticated']) {
    // please mind you need to add extra security checks here (see comments below)
    readfile($file); // if it php include it. you may need to extend this code
}else{
   // bad auth error
}

      

+1


source


Okay, here's my answer - and it's true that the best answer is no. But images / js / css are relatively important in development (before they become public, when they live) and client previews dictate that we cannot use an IP based apache rule. So the rule (above, slightly modified)

RewriteEngine On

# Exclude the public and error directories from authentication
RewriteRule ^(public|error)($|/) - [L]

# Perform authentication via php
RewriteCond %{REQUEST_FILENAME} !auth.php
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .* auth.php?requested_file=$0 [QSA,L]

      

(because I needed multiple subdirectories where the content was actually public, read: images / css / js used in the login page)

and the corresponding php looks like this; for

        if($authenticated){
            if($extension == 'php'){    

                call_user_func(function(){

                    $file_name = func_get_arg(0);

                    $path = getcwd();
                    chdir(pathinfo($file_name,PATHINFO_DIRNAME));
                    return include($file_name);
                    chdir($path);

                }, $file_name);

            } else {

                //set cache headers so the browsers don't have to refresh all the
                // static content
                header_remove('X-Powered-By');
                header_remove('Transfer-Encoding');
                header_remove('Cache-Control');
                header_remove('Pragma');
                header_remove('Expires');
                //header('Expires:');

                header('Content-type: '.$mime_type);
                readfile($file_name);
            }
        }

      



what it does is run php with call_user_func()

to stop polluting the namespace, include()

execute PHP and chdir()

to make sure the script gets the correct current working directory.

This is the "easy" part; content headers and mime type must be "guessed" (I used finfo for mime types, but it has a bug in 2013 and this only exacerbates the problem) but even apache can't do it 100% correctly ...

Then remove the cache control headers for the images, otherwise you will not only be frequently as php pages, but also ...

suffice it to say; you only need to do this if you have thick pipes and a lot of cpu cycles that you don't need ...

+1


source


I usually use this

$redi_ext = $_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
$php_verify = strpos($redi_ext, ".php");
if($php_verify !== false){ header('location: PAGE_NOT_FOUND_URL'); }

      

0


source







All Articles