PHP Protect Include Files
Including files plays an important role in PHP development. For example, your app may consist of a main plugin file that includes several smaller files, each of which contains some distinct bit of functionality. When including such files, it’s a good idea to protect them against direct access. This tutorial rounds up a bunch of ways to do the job.
Compare realpath data
This technique is a common, effective way to deny direct access to any PHP file. Here are four code snippets to demonstrate the technique:
<?php if (realpath(__FILE__) === realpath($_SERVER['SCRIPT_FILENAME'])) die(); ?>
<?php if (realpath(__FILE__) === realpath($_SERVER['SCRIPT_FILENAME'])) exit('Do not access this file directly.'); ?>
<?php if (realpath(__FILE__) === realpath($_SERVER['SCRIPT_FILENAME'])) header('Location: https://wp-tao.com/'); ?>
<?php if (realpath(__FILE__) === realpath($_SERVER['SCRIPT_FILENAME'])) header('HTTP/1.0 403 Forbidden'); ?>
Just to reiterate, you only need to use one of these lines to protect your include file. Simply choose whichever one you would like to use, and then copy/paste it to the very top of the include file. To verify that it works, try accessing the file in a browser.
Here is a more specific version of the above technique:
<?php if (realpath(__FILE__) == realpath($_SERVER['DOCUMENT_ROOT'] . $_SERVER['SCRIPT_NAME'])) die(); ?>
Here we use $_SERVER['DOCUMENT_ROOT']
to get the full path of the include file. Recommended to test this technique thoroughly to make sure that the paths are making sense and the comparison is working.
Compare file names
Here is another technique for denying direct requests:
<?php if (preg_match('#'. basename(__FILE__) .'#', $_SERVER['PHP_SELF'])) die(); ?>
Here we are using preg_match()
to compare the file name with that provided by $_SERVER['PHP_SELF']
. As with all of these techniques, this snippet should be placed at the top of whichever file you are trying to protect. No editing required.
File-specific protection
If you have a specific include that you would like to protect (or target for whatever reason), you can add the following line to the script that is including other files:
<?php define('WHATEVER_KEYWORD'); ?>
Then, in each of the include files, add this bit:
<?php if (!defined('WHATEVER_KEYWORD')) die(); ?>
Then any direct request for the include files will die. Feel free to change the WHATEVER_KEYWORD
part to something more suitable (it’s only meant as an example of the technique).
Protecting WordPress includes
If you use WordPress, it can be a good idea to protect theme template files (such as functions.php
) by adding one of the following lines:
<?php if (!defined('ABSPATH')) exit; ?>
<?php defined('ABSPATH') or die('Sorry dude!'); ?>
<?php if (!function_exists('add_action')) die(); ?>
Again, you only need to include one of these lines at the top of whichever file you are wanting to protect. Here is another example, showing a technique for protecting the functions.php
file from direct access:
<?php if ('functions.php' == basename($_SERVER['SCRIPT_FILENAME'])) die(); ?>
..and a similar technique for the comments.php
template:
<?php if (!empty($_SERVER['SCRIPT_FILENAME']) && 'comments.php' == basename($_SERVER['SCRIPT_FILENAME'])) {
die ('Please do not load this page directly. Thanks!');
} ?>
Bonus: Check the file is an include
Here is a related technique that may prove useful:
<?php if (__FILE__ != $_SERVER['SCRIPT_FILENAME']) { /* this is an include file */ } ?>
This snippet compares the file constant against the script’s filename to see if it is an included file. So you can do something specific for includes.