PHP: проверьте, загружен ли файл напрямую, а не включен?

Есть ли способ предотвратить просмотр пользователем файла, но все еще использовать его как включенный в другой файл в 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 . Вуаля.

Минусы:

  • (!) сильно зависит от конфигурации Apache (поэтому вы уязвимы, если кто-то пренебрегает этой строкой) – и в таком случае браузер может увидеть весь PHP-скрипт в открытом виде, поскольку он не будет передан в PHP (очень плохо!)
  • это может раздражать, чтобы переименовать ваши включенные файлы

Плюсы:

  • дает понять, какие файлы должны быть включены, а какие нет в вашем коде
  • вам не нужно перемещать иерархию файлов вокруг

Лично я предпочел бы просто перемещать файлы в каталог за пределами корня документа, но если у вас есть большое унаследованное приложение, это можно было бы быстрее изменить.

Ссылка: 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:

коммерческий

  • ИонКуба PHP Encoder
  • Zend Guard
  • phpSHIELD
  • SourceGuardian

Свободно