Есть ли способ предотвратить просмотр пользователем файла, но все еще использовать его как включенный в другой файл в PHP ?
Если вы используете
define('APP_RAN');
в файл, который включает его, а затем положить
if(!defined('APP_RAN')){ die(); }
или альтернативно
defined('APP_RAN') or die();
(что легче читать)
в включенных файлах он будет умирать, если вы получите доступ к ним напрямую.
Вероятно, было бы лучше разместить все ваши включенные файлы выше вашего DocumentRoot.
Например, если ваша индексная страница находится на
/my/server/domain/public_html
Вы должны поместить включенные файлы в
/my/server/domain/
Не используйте глобальный код в своих файлах, а только функции и методы. Тогда нет необходимости заботиться о включении и прямом использовании.
Мое предложение:
<?php if (__FILE__ == $_SERVER['SCRIPT_FILENAME']) { header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found'); exit("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<html><head>\r\n<title>404 Not Found</title>\r\n</head><body>\r\n<h1>Not Found</h1>\r\n<p>The requested URL " . $_SERVER['SCRIPT_NAME'] . " was not found on this server.</p>\r\n</body></html>"); } else { // your code } ?>
1.) он проверяет, вызван ли он непосредственно иначе, он выдает ошибку
2.) он выдает 404 стандартную страницу ошибки apache (пожалуйста, сравните с вашей оригинальной страницей 404 или просто включите эту страницу), чтобы добавить защиту через неясность
3.) else-part избегает частичного выполнения, пока файл загружается в живую среду (PHP не ждет «?>»). Это вам не нужно, если ваш включенный файл содержит только одну функцию / один класс.
Просто сохраните файл за пределами вашего веб-корня.
if (!defined('FLAG_FROM_A_PARENT')) // Works in all scenarios but I personally dislike this if (__FILE__ == get_included_files()[0]) // Doesn't work with PHP prepend unless calling [1] instead. if (__FILE__ == $_SERVER['DOCUMENT_ROOT'] . $_SERVER['SCRIPT_FILENAME']) // May break on Windows due to mixed DIRECTORY_SEPARATOR if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME'])) // Doesn't work with files with the same basename but different paths if (realpath(__FILE__) == realpath($_SERVER['DOCUMENT_ROOT'].$_SERVER['SCRIPT_NAME'])) // Seems to do the trick
if (__FILE__ == $_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF']){ die("Direct access forbidden"); }
Он работает независимо от того, где он находится. (Приветствует @ col-sharpnel за то, что указывает на неполное, но хорошее решение.)
Есть функция get_included_files . Вы можете использовать его так:
if ( empty(get_included_files()) ) die("Direct access forbidden");
В Apache это легко: добавьте директиву <Files>
в ваш .htaccess, чтобы предотвратить доступ к нему из веб-браузера. Это не относится к PHP, и хорошей практикой является скрыть несколько файлов из браузера (хотя обычно вы пытаетесь объединить все незащищенные файлы в один каталог).
<Files="myprivatefile.php"> deny from all </Files>
Под другим веб-сервером вы можете скрыть файл из корня вашего документа, но в некоторых случаях (например, если ваши скрипты open_basedir
'd строгим образом), это не сработает.
if($argv[0] == basename(__FILE__)) include_once('/path/to/file.php');
Проверьте, сколько файлов включено …
if(count(get_required_files()) < 2) { die(); }
Или сколько минимум должно быть, а не 2
В этой теме есть много хороших ответов – вот что еще не упоминалось.
Вы можете назвать ваши включенные файлы PHP с i
в расширении, например someincludedfile.phpi
а затем настроить Apache так, чтобы он не обслуживал файлы phpi
. Вуаля.
Минусы:
Плюсы:
Лично я предпочел бы просто перемещать файлы в каталог за пределами корня документа, но если у вас есть большое унаследованное приложение, это можно было бы быстрее изменить.
Ссылка: http://www.ducea.com/2006/07/21/apache-tips-tricks-deny-access-to-certain-file-types/
Я бы выбрал решение Chacha102 .
Кроме того, поскольку в названии вопроса указано « как проверить », вы также можете сделать это, не указав переменную, используя
// secret.php is the name of this file. if($_SERVER["SCRIPT_FILENAME"]=='secret.php') die();
Если вы хотите остановить его из когда-либо отображаемого, когда он не включен, это более автоматизированный способ.
if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])) header("HTTP/1.0 404 Not Found");
Таким образом, он будет работать, если вы в конечном итоге измените имя файла или что-то еще.
Просто для расширения решений с переменными $_SERVER
– ниже – маленький .php-файл, а в комментариях – копия теста bash
я сделал на Ubuntu; Дело в том, что эти переменные могут сильно изменяться в зависимости от типа доступа и используются ли символические ссылки ( обратите внимание также, что в приведенном ниже коде мне нужно избежать « ?\>
» в выражении echo, иначе синтаксис разрывы цвета, удалите обратную косую черту, если пытаетесь выполнить код ):
<?php function report($label, $value) { printf ("%23s: %s\n", $label, $value); } report("DOCUMENT_ROOT.PHP_SELF", $_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF'] ); report("SCRIPT_FILENAME", $_SERVER['SCRIPT_FILENAME'] ); report("__FILE__", __FILE__ ); report("PHP_SAPI", PHP_SAPI ); /* # the test (bash): home~$ mkdir /tmp/ptest home~$ cd /tmp/ptest/ ptest$ ln -s /real/path/to/varcheck.php . ptest$ echo '<? require_once "varcheck.php"; ?\>' > varcheckincl.php # ... and in a separate terminal, run # php (>5.4) cli server at same (/tmp/ptest) location: ptest$ php-5.4.10 -S localhost:8000 # back to first terminal, the test - and output: ptest$ php varcheck.php DOCUMENT_ROOT.PHP_SELF: varcheck.php SCRIPT_FILENAME: varcheck.php __FILE__: /real/path/to/varcheck.php PHP_SAPI: cli ptest$ php -r 'require_once "varcheck.php";' DOCUMENT_ROOT.PHP_SELF: - SCRIPT_FILENAME: __FILE__: /real/path/to/varcheck.php PHP_SAPI: cli ptest$ php varcheckincl.php DOCUMENT_ROOT.PHP_SELF: varcheckincl.php SCRIPT_FILENAME: varcheckincl.php __FILE__: /real/path/to/varcheck.php PHP_SAPI: cli ptest$ wget http://localhost:8000/varcheck.php -q -O - DOCUMENT_ROOT.PHP_SELF: /tmp/ptest/varcheck.php SCRIPT_FILENAME: /tmp/ptest/varcheck.php __FILE__: /real/path/to/varcheck.php PHP_SAPI: cli-server ptest$ wget http://localhost:8000/varcheckincl.php -q -O - DOCUMENT_ROOT.PHP_SELF: /tmp/ptest/varcheckincl.php SCRIPT_FILENAME: /tmp/ptest/varcheckincl.php __FILE__: /real/path/to/varcheck.php PHP_SAPI: cli-server */ ?>
Вы должны использовать расширение для кодировщика и загрузчика PHP: