У меня есть php-файл, который я включаю в свой php-скрипт, но я не хочу, чтобы люди могли напрямую запускать файл (без включения). Как я могу предотвратить это?
Не включайте скрипты, недоступные через HTTP . Например, защищая подпапку или перемещая их выше корня документа.
Если вы не можете этого сделать, define()
что-то вроде IS_INCLUDED
в вашем основном скрипте и exit;
если эта константа не defined()
в вашем включенном скрипте.
Проверка того, является ли скрипт родительским процессом PHP, может быть не лучшей идеей для предотвращения прямого запроса на включение файла include. Но это может быть удобно во многих других случаях, например, в модулях AJAX и т. Д. Я не собираюсь начинать новую тему.
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 not work on Windows due to mixed DIRECTORY_SEPARATOR (machine specific) if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME'])) // Doesn't work with files with the same basename but different paths if (defined('FLAG_FROM_A_PARENT')) // Works in all scenarios but I personally dislike this if (realpath(__FILE__) == realpath($_SERVER['DOCUMENT_ROOT'] . $_SERVER['SCRIPT_FILENAME'])) // Should work flawlessly
Имейте в виду, что некоторые машины, использующие виртуальные пути, могут возвращать разные пути в разных php-компонентах. realpath () – ваш друг для этого.
Я использую константу контролера , определенную в скрипте «включая», и скрипт «включено» ищет его.
Пример:
/* main.php */ define('SENTINEL', 1); include "included.inc.php" /* included.inc.php */ if (!defined('SENTINEL')) die("Wanted to be smart?? Nice try.");
2 решения для хорошей защиты:
с htaccess :
RedirectMatch 404 "\.(sql|sh|java|class|inc\.php)$"
Или в / etc / apache2 / sites-enabled :
<VirtualHost *:80> #... RedirectMatch 404 "\.(sql|sh|java|class|inc\.php)$" #... </VirtualHost>
Затем назовите свой файл следующим образом: myInternalFileIncludeOnly.inc.php
С помощью этого примера кода PHP может обнаруживать:
if( get_included_files()[0] == __FILE__ ){ echo '2.php direct access'; }else{ echo '2.php was included'; }
EDIT : см. Ответ Тима, поэтому, если у вас есть preend include (cf php.ini), используйте это:
if( (!ini_get('auto_prepend_file') && get_included_files()[0] === __FILE__) || ini_get('auto_prepend_file') && (($__FILE__=str_replace('\\','/',__FILE__)) === str_replace('\\','/',$_SERVER['DOCUMENT_ROOT'].$_SERVER['SCRIPT_FILENAME']) || $__FILE__ === str_replace('\\','/',$_SERVER['SCRIPT_FILENAME']) ) ) echo '2.php direct access',"\n";
Я видел этот шаблон в некоторых приложениях:
define('SOMETHING', 'SOMEVALUE');
if(!defined('SOMETHING')) return;
Вложенные PHP-файлы должны содержать определения класса / функции / переменных, а не встроенные логические / выходные.
Запуск их непосредственно тогда, по существу, не-op.