Запретить прямой доступ к файлу php - PullRequest
155 голосов
/ 03 января 2009

У меня есть php-файл, который я буду использовать исключительно для включения. Поэтому я хотел бы выдать ошибку вместо того, чтобы выполнить ее, когда к ней обращаются напрямую, введя URL-адрес вместо включения.

В основном мне нужно выполнить проверку в php-файле следующим образом:

if ( $REQUEST_URL == $URL_OF_CURRENT_PAGE ) die ("Direct access not premitted");

Есть ли простой способ сделать это?

Ответы [ 34 ]

172 голосов
/ 03 января 2009

Добавьте это на страницу, которую хотите включить только

<?php
if(!defined('MyConst')) {
   die('Direct access not permitted');
}
?>

затем на страницах, которые включают его, добавьте

<?php
define('MyConst', TRUE);
?>
156 голосов
/ 03 января 2009

Самый простой способ для типичной ситуации "PHP-приложение, работающее на сервере Apache, которым вы можете или не можете полностью управлять", - это поместить ваши включения в каталог и запретить доступ к этому каталогу в вашем файле .htaccess. Чтобы избавить людей от проблем с Google, если вы используете Apache, поместите его в файл с именем «.htaccess» в каталоге, который вам не нужен:

Deny from all

Если вы на самом деле имеете полный контроль над сервером (в наши дни это более распространено даже для небольших приложений, чем когда я впервые написал этот ответ), лучший способ - разместить файлы, которые вы хотите защитить, за пределами каталога, который ваш веб-сервер служит от. Так что, если ваше приложение находится в /srv/YourApp/, настройте сервер для обслуживания файлов из /srv/YourApp/app/ и вставьте включения в /srv/YourApp/includes, чтобы буквально не было URL-адресов, которые могли бы получить к ним доступ.

106 голосов
/ 03 января 2009

У меня есть файл, который мне нужно действовать по-разному, когда он включен, и при прямом доступе (в основном, print() против return()). Вот некоторый модифицированный код:

if(count(get_included_files()) ==1) exit("Direct access not permitted.");

Доступ к файлу всегда является включенным файлом, поэтому == 1.

31 голосов
/ 03 января 2009

Лучший способ предотвратить прямой доступ к файлам - это разместить их вне корня документа веб-сервера (обычно на один уровень выше). Вы по-прежнему можете включать их, но никто не сможет получить к ним доступ через http-запрос.

Обычно я иду до конца и помещаю все свои файлы PHP вне корня документа, кроме файла начальной загрузки - одиночного index.php в корне документа, который начинает маршрутизацию всего сайта / применение.

25 голосов
/ 03 января 2009

Альтернативой (или дополнением) решения Чака было бы запретить доступ к файлам, соответствующим определенному шаблону, добавив нечто подобное в ваш файл .htaccess

<FilesMatch "\.(inc)$">
    Order deny,allow
    Deny from all
</FilesMatch>
24 голосов
/ 27 марта 2014

1: проверка количества включенных файлов

if( count(get_included_files()) == ((version_compare(PHP_VERSION, '5.0.0', '>='))?1:0) )
{
    exit('Restricted Access');
}

Логика: PHP завершается, если не выполнено минимальное число включений. Обратите внимание, что до PHP5 базовая страница не считается включенной.


2: определение и проверка глобальной константы

// In the base page (directly accessed):
define('_DEFVAR', 1);

// In the include files (where direct access isn't permitted):
defined('_DEFVAR') or exit('Restricted Access');

Логика: Если константа не определена, то выполнение не начнется с базовой страницы, и PHP прекратит выполнение.


3: удаленная авторизация адреса

// Call the include from the base page(directly accessed):
$includeData = file_get_contents("http://127.0.0.1/component.php?auth=token");

// In the include files (where direct access isn't permitted):
$src = $_SERVER['REMOTE_ADDR']; // Get the source address
$auth = authoriseIP($src); // Authorisation algorithm
if( !$auth ) exit('Restricted Access');

Недостатком этого метода является изолированное выполнение, если токен сеанса не предоставлен с внутренним запросом. Проверьте через адрес обратной связи в случае конфигурации с одним сервером или белый список адресов для многосерверной или серверной инфраструктуры с балансировкой нагрузки.


4: авторизация токена

Как и в предыдущем методе, можно использовать GET или POST для передачи токена авторизации во включаемый файл:

if($key!="serv97602"){header("Location: ".$dart);exit();}

Очень грязный метод, но, возможно, самый безопасный и универсальный одновременно при правильном использовании.


5: Конфигурация веб-сервера

Большинство серверов позволяют назначать разрешения для отдельных файлов или каталогов. Вы можете поместить все свои включения в такие ограниченные каталоги и настроить сервер на их запрет.

Например, в APACHE конфигурация сохраняется в файле .htaccess. Учебное пособие здесь .

Обратите внимание , однако, что специфичные для сервера конфигурации не рекомендуются мной, потому что они плохо переносимы между различными веб-серверами. В тех случаях, когда алгоритм deny сложен или список запрещенных каталогов довольно большой, он может сделать сеансы реконфигурации только ужасными. В конце концов, лучше всего обработать это в коде.


6: Размещение включает в безопасном каталоге за пределами корня сайта

Наименее предпочтительный из-за ограничений доступа в серверных средах, но довольно мощный метод, если у вас есть доступ к файловой системе.

//Your secure dir path based on server file-system
$secure_dir=dirname($_SERVER['DOCUMENT_ROOT']).DIRECTORY_SEPARATOR."secure".DIRECTORY_SEPARATOR;
include($secure_dir."securepage.php");

Логика:

  • Пользователь не может запросить какой-либо файл за пределами папки htdocs, поскольку ссылки будут выходить за рамки адресной системы сайта.
  • Сервер php напрямую обращается к файловой системе и, следовательно, может обращаться к файлам на компьютере так же, как это делает обычная программа с необходимыми привилегиями.
  • Поместив включаемые файлы в этот каталог, вы можете гарантировать, что php-сервер получит к ним доступ, в то время как горячая ссылка будет запрещена для пользователя.
  • Даже если настройка доступа к файловой системе веб-сервера не была выполнена должным образом, этот метод предотвратит случайное обнародование этих файлов.

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

15 голосов
/ 03 января 2009

На самом деле мой совет - использовать все эти лучшие практики.

  • Поместите документы вне webroot ИЛИ в каталог, к которому веб-сервер не имеет доступа И
  • Используйте определение в ваших видимых документах, которые проверяют скрытые документы:
      if (!defined(INCL_FILE_FOO)) {
          header('HTTP/1.0 403 Forbidden');
          exit;
      }

Таким образом, если файлы как-то теряются (ошибочная операция ftp), они все еще защищены.

7 голосов
/ 10 марта 2010

Однажды у меня была эта проблема, решенная с помощью:

if (strpos($_SERVER['REQUEST_URI'], basename(__FILE__)) !== false) ...

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

5 голосов
/ 29 марта 2013

Вам лучше создать приложение с одной точкой входа, то есть все файлы должны быть доступны из index.php

Поместите это в index.php

define(A,true);

Эта проверка должна выполняться в каждом связанном файле (через require или include)

defined('A') or die(header('HTTP/1.0 403 Forbidden'));
4 голосов
/ 07 мая 2010

Что за Joomla! do определяет константу в корневом файле и проверяет, определена ли она во включаемых файлах.

defined('_JEXEC') or die('Restricted access');

или еще

можно хранить все файлы вне досягаемости http-запроса, размещая их вне каталога webroot, как рекомендует большинство фреймворков, таких как CodeIgniter.

или даже поместив файл .htaccess в папку include и правила записи, вы можете запретить прямой доступ.

...