@EugeneLazutkin дает пример, где он называет назначенную функцию, чтобы иметь возможность использовать shortcut()
как внутреннюю ссылку на себя. Джон Ресиг дает другой пример - копирование рекурсивной функции, назначенной другому объекту в его учебном пособии Learning Advanced Javascript . Хотя назначение функций свойствам не является строго вопросом здесь, я рекомендую активно пробовать учебник - запустите код, нажав кнопку в правом верхнем углу, и дважды щелкните код для редактирования по своему вкусу.
Примеры из учебника: рекурсивные вызовы в yell()
:
Тесты завершаются, когда исходный объект ниндзя удален. (стр. 13)
var ninja = {
yell: function(n){
return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
}
};
assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." );
var samurai = { yell: ninja.yell };
var ninja = null;
try {
samurai.yell(4);
} catch(e){
assert( false, "Uh, this isn't good! Where'd ninja.yell go?" );
}
Если вы назовете функцию, которая будет называться рекурсивно, тесты пройдут. (стр. 14)
var ninja = {
yell: function yell(n){
return n > 0 ? yell(n-1) + "a" : "hiy";
}
};
assert( ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!" );
var samurai = { yell: ninja.yell };
var ninja = {};
assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." );
Самый простой способ для общего «PHP-приложения, работающего на сервере Apache, который вы можете или не можете полностью контролировать», - включить ваши включения в каталог и запретить доступ к этому каталогу в вашем файле .htaccess. Чтобы спасти людей от проблем с Google, если вы используете Apache, поместите это в файл с именем «.htaccess» в каталог, который вы не хотите быть доступным:
Deny from all
Если вы действительно имеют полный контроль над сервером (более распространенный в наши дни даже для небольших приложений, чем когда я впервые написал этот ответ), лучший подход заключается в том, чтобы хранить файлы, которые вы хотите защитить, за пределами каталога, от которого работает ваш веб-сервер. Поэтому, если ваше приложение находится в /srv/YourApp/
, установите сервер для работы с файлами из /srv/YourApp/app/
и поместите его в /srv/YourApp/includes
, так что там буквально нет никакого URL-адреса, который может получить к ним доступ.
Добавьте это на страницу, которую вы хотите включить только
<?php
if(!defined('MyConst')) {
die('Direct access not permitted');
}
?>
, затем на страницы, которые включают ее, добавьте
<?php
define('MyConst', TRUE);
?>
somefile.php
на вашем сервере и добавили в него свое определение, это все равно не позволяет им напрямую обращаться к включенному файлу. Он позволит им включать "включить" ваши файлы библиотеки, но если они будут достаточно далеко, чтобы создавать файлы на вашем сервере и зная ваши сценарии define / include, у вас есть другие проблемы, которые, вероятно, отрицают возможность записи собственного файла с вашим определением в первую очередь.
– James
10 September 2013 в 17:43
if (basename($_SERVER['PHP_SELF']) == basename(__FILE__)) { die('Access denied'); };
Что такое Joomla! это определение константы в корневом файле и проверка того, определено ли это во входящих файлах.
defined('_JEXEC') or die('Restricted access');
или
можно сохранить все файлы вне досягаемости http, помещая их вне каталога webroot, поскольку большинство фреймворков, таких как CodeIgniter, рекомендуют.
или даже размещая файл .htaccess внутри папки include и правила записи, вы можете предотвратить прямой доступ.
Помимо пути .htaccess, я видел полезную модель в различных рамках, например, в ruby on rails. У них есть отдельный каталог pub / в корневом каталоге приложения, а каталоги библиотек живут в каталогах на уровне как pub /. Что-то вроде этого (не идеальное, но вы получаете идею):
app/
|
+--pub/
|
+--lib/
|
+--conf/
|
+--models/
|
+--views/
|
+--controllers/
Вы настроили свой веб-сервер для использования pub / в качестве корня документа. Это обеспечивает лучшую защиту ваших скриптов: в то время как они могут протянуться из корня документа для загрузки необходимых компонентов, невозможно получить доступ к компонентам из Интернета. Другое преимущество, кроме безопасности, заключается в том, что все в одном месте.
Эта настройка лучше, чем просто создание проверок в каждом отдельном файле, поскольку сообщение «доступ не разрешено» является ключом к атакующим, и это лучше, чем .htaccess, потому что он не основан на белых списках: если вы испортили расширения файлов, он не будет отображаться в каталогах lib /, conf / etc.
<?php
if (eregi("YOUR_INCLUDED_PHP_FILE_NAME", $_SERVER['PHP_SELF'])) {
die("<h4>You don't have right permission to access this file directly.</h4>");
}
?>
поместите код выше в верхнюю часть вашего включенного php-файла.
ex:
<?php
if (eregi("some_functions.php", $_SERVER['PHP_SELF'])) {
die("<h4>You don't have right permission to access this file directly.</h4>");
}
// do something
?>
Вы можете использовать следующий ниже метод, хотя он имеет недостаток, потому что его можно подделать, за исключением случаев, когда вы можете добавить еще одну строку кода, чтобы убедиться, что запрос приходит только с вашего сервера либо с помощью Javascript. Вы можете поместить этот код в раздел «Тело» вашего HTML-кода, поэтому там отображается ошибка.
<?
if(!isset($_SERVER['HTTP_REQUEST'])) { include ('error_file.php'); }
else { ?>
Поместите свой другой код HTML здесь
<? } ?>
Завершите его так , поэтому вывод ошибки всегда будет отображаться внутри секции тела, если это так, как вы хотите.
Лучший способ предотвратить прямой доступ к файлам - разместить их вне корня документа веб-сервера (обычно на одном уровне выше). Вы все еще можете включить их, но нет возможности доступа к ним через HTTP-запрос.
Обычно я прохожу весь путь и размещаю все мои файлы PHP за пределами корня документа, кроме bootstrap file - одиночный index.php в корневом каталоге документа, который начинает маршрутизацию всего веб-сайта / приложения.
На самом деле, мой совет состоит в том, чтобы делать все эти лучшие практики.
if (!defined(INCL_FILE_FOO)) {
header('HTTP/1.0 403 Forbidden');
exit;
}
Таким образом, если файлы каким-то образом перестают работать (операция errant ftp), они все еще защищены.
Следующий код используется в CMS Flatnux ( http://flatnux.altervista.org ):
if ( strpos(strtolower($_SERVER['SCRIPT_NAME']),strtolower(basename(__FILE__))) )
{
header("Location: ../../index.php");
die("...");
}
Мой ответ несколько отличается в подходе, но включает в себя многие из приведенных здесь ответов. Я бы рекомендовал многопростовый подход:
defined('_SOMECONSTANT') or die('Hackers! Be gone!');
ОДНАКО defined or die
подход имеет ряд недостатков. Во-первых, это настоящая боль в предположениях для тестирования и отладки. Во-вторых, это связано с ужасающим, умопомрачительно скучным рефакторингом, если вы передумаете. "Найти и заменить!" ты говоришь. Да, но насколько ты уверен, что все написано точно так же везде, хммм? Теперь умножьте это на тысячи файлов ... o.O
И тогда есть .htaccess. Что произойдет, если ваш код будет распространен на сайтах, где администратор не так скрупулезен? Если вы полагаетесь только на .htaccess для защиты ваших файлов, вам также понадобится: a) резервная копия, b) ящик тканей для высыхания ваших слез, c) огнетушитель, чтобы погасить огонь во всей ленте от людей используя ваш код.
Итак, я знаю, что вопрос задает «самый простой», но я думаю, что это требует более «защитного кодирования».
Я предлагаю:
require('ifyoulieyougonnadie.php');
(не include()
и в качестве замены для defined or die
) ifyoulieyougonnadie.php
выполните некоторые логические действия - проверьте различные константы, вызывающий скрипт, локальное тестирование и т. д., а затем реализовать ваш die(), throw new Exception, 403
и т. д. Я создаю свою собственную фреймворк с двумя возможными точками входа - основной index.php (инфраструктура Joomla) и ajaxrouter.php (моя фреймворк) - поэтому в зависимости от точки входа я проверяю разные вещи. Если запрос на ifyoulieyougonnadie.php
не поступает из одного из этих двух файлов, я знаю, что принимаются махинации! Но что, если я добавлю новую точку входа? Не беспокойся. Я просто изменяю ifyoulieyougonnadie.php
, и меня сортируют, а также нет «найти и заменить». Ура! Что делать, если я решил переместить некоторые мои скрипты, чтобы создать другую структуру, которая не имеет одинаковых констант defined()
? ... Ура! ^ _ ^ Я нашел, что эта стратегия делает разработку намного веселее и намного меньше:
/**
* Hmmm... why is my netbeans debugger only showing a blank white page
* for this script (that is being tested outside the framework)?
* Later... I just don't understand why my code is not working...
* Much later... There are no error messages or anything!
* Why is it not working!?!
* I HATE PHP!!!
*
* Scroll back to the top of my 100s of lines of code...
* U_U
*
* Sorry PHP. I didn't mean what I said. I was just upset.
*/
// defined('_JEXEC') or die();
class perfectlyWorkingCode {}
perfectlyWorkingCode::nowDoingStuffBecauseIRememberedToCommentOutTheDie();
Я нашел это php-единственное и неизменное решение, которое работает как с http, так и с cli:
Определить функцию:
function forbidDirectAccess($file) {
$self = getcwd()."/".trim($_SERVER["PHP_SELF"], "/");
(substr_compare($file, $self, -strlen($self)) != 0) or die('Restricted access');
}
Вызвать функцию в файле, который вы хотите запретить прямой доступ к:
forbidDirectAccess(__FILE__);
Большинство решений, приведенных выше для этого вопроса, не работают в режиме Cli.
Сделайте что-то вроде:
<?php
if ($_SERVER['SCRIPT_FILENAME'] == '<path to php include file>') {
header('HTTP/1.0 403 Forbidden');
exit('Forbidden');
}
?>
Самый простой способ - установить некоторую переменную в файле, который включает include, например
$including = true;
. Затем в файл, который включен, проверьте переменную
if (!$including) exit("direct access not permitted");
У меня была эта проблема один раз, решена с помощью:
if (strpos($_SERVER['REQUEST_URI'], basename(__FILE__)) !== false) ...
, но идеальным решением является размещение файла за пределами корня документа веб-сервера, как указано в другом anwser.
<?php
$url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
if (false !== strpos($url,'.php')) {
die ("Direct access not premitted");
}
?>
Ранее упомянутое решение с проверкой версии PHP добавлено:
$max_includes = version_compare(PHP_VERSION, '5', '<') ? 0 : 1;
if (count(get_included_files()) <= $max_includes)
{
exit('Direct access is not allowed.');
}
Я предлагаю не использовать $_SERVER
по соображениям безопасности. Вы можете использовать переменную типа $root=true;
в первом файле, которая включала другую. и используйте isset($root)
в начале второго файла, который будет включен.
Вы можете использовать стиль phpMyAdmin:
/**
* block attempts to directly run this script
*/
if (getcwd() == dirname(__FILE__)) {
die('Attack stopped');
}
Альтернативой (или дополнением) к решению Чака было бы запретить доступ к файлам, соответствующим определенному шаблону, помещая что-то подобное в ваш .htaccess файл
<FilesMatch "\.(inc)$">
Order deny,allow
Deny from all
</FilesMatch>
У меня есть файл, который мне нужно действовать по-разному, когда он включен vs, когда он доступен напрямую (в основном, print()
vs return()
). Вот некоторые модифицированные коды:
if(count(get_included_files()) ==1) exit("Direct access not permitted.");
accessed всегда является включенным файлом, следовательно, == 1. & nbsp;
Если более точно, вы должны использовать это условие:
if (array_search(__FILE__, get_included_files()) === 0) {
echo 'direct access';
}
else {
echo 'included';
}
get_included_files () возвращает индексированный массив, содержащий имена всех включенных файлов (если файл исполняется beign, тогда он был включен и его имя находится в массиве). Итак, когда файл имеет прямой доступ, его имя является первым в массиве, все остальные файлы в массиве включены.
Я хотел напрямую ограничить доступ к файлу PHP, но также иметь возможность называть его через jQuery $.ajax (XMLHttpRequest)
. Вот что сработало для меня.
if (empty($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_SERVER["HTTP_X_REQUESTED_WITH"] != "XMLHttpRequest") {
if (realpath($_SERVER["SCRIPT_FILENAME"]) == __FILE__) { // direct access denied
header("Location: /403");
exit;
}
}
if( count(get_included_files()) == ((version_compare(PHP_VERSION, '5.0.0', '>='))?1:0) )
{
exit('Restricted Access');
}
Логика: PHP завершает работу, если минимальное количество count не выполняется. Обратите внимание, что до PHP5 базовая страница не считается include.
// 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');
Логика: если константа isn ' t, то выполнение не начиналось с базовой страницы, и PHP прекратил выполнение.
// 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');
Недостаток с этим метод является изолированным исполнением, если токен-токен не предоставляется с внутренним запросом. Проверить через обратный адрес в случае конфигурации одного сервера или белый список адресов для серверной инфраструктуры с несколькими серверами или с балансировкой нагрузки.
Как и предыдущий метод, можно использовать GET или POST для передачи токена авторизации в файл include:
if($key!="serv97602"){header("Location: ".$dart);exit();}
Очень грязный метод, но также, возможно, самый безопасный и универсальный на (g7) 5: Конфигурация веб-сервера
Большинство серверов позволяют назначать разрешения для отдельных файлов или каталогов. Вы можете разместить все свои включения в таких ограниченных каталогах и настроить сервер на их отказ.
Например, в APACHE конфигурация сохраняется в файле .htaccess
. Tutorial здесь .
Обратите внимание: , однако, что настройки для сервера не рекомендуются мной, потому что они плохо переносимы на разных веб-серверах. В таких случаях, когда алгоритм deny является сложным или список запрещенных каталогов довольно велик, он может сделать сеансы реконфигурации довольно ужасными. В конце концов, лучше всего обрабатывать это в коде.
Наименее предпочтительным из-за ограничений доступа в серверных средах, но довольно мощный метод, если у вас есть доступ к файловой системе.
//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-скрипты там, конечно, за исключением файла index.php, поскольку на момент включения пароль не потребуется, поскольку это потребуется только для http доступ. то, что он будет делать, также предоставляет вам возможность доступа к вашим скриптам в случае, если вы этого хотите, поскольку у вас будет пароль для доступа к этому каталогу. вам нужно будет установить файл .htaccess для каталога и файл .htpasswd для аутентификации пользователя.
ну, вы также можете использовать любое из вышеперечисленных решений, если вы считаете, что вам не нужно доступ к этим файлам обычно, потому что вы всегда можете получить к ним доступ через cPanel и т. д.
Надеемся, что это поможет
Я не нашел предложений с .htaccess настолько хорошими, что мог заблокировать другой контент в этой папке, который вы, возможно, захотите разрешить пользователю, это мое решение:
$currentFileInfo = pathinfo(__FILE__);
$requestInfo = pathinfo($_SERVER['REQUEST_URI']);
if($currentFileInfo['basename'] == $requestInfo['basename']){
// direct access to file
}
debug_backtrace() || die ("Direct access not permitted");
Самый простой способ - сохранить ваши данные за пределами веб-каталога. Таким образом, у сервера есть доступ к ним, но нет внешней машины. Единственная нижняя сторона - вам нужно иметь доступ к этой части вашего сервера. Потенциал роста не требует настройки, конфигурации или дополнительного стресса кода / сервера.
Лучше построить приложение с одной точкой входа, т. е. все файлы должны быть достигнуты из index.php
Поместите это в index.php
define(A,true);
Эта проверка должна запускать в каждом связанном файле (через require или include)
defined('A') or die(header('HTTP/1.0 403 Forbidden'));
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
сделает работу гладкой
BASEPATH
const
установлен в файле index.php
, который лежит в нижней части древовидной структуры. CI перезаписывает URL-адреса, поэтому в любом случае нет необходимости в доступе к скриптам.
– jimasun
28 October 2016 в 15:37
<Files ~ "\.inc$">
Order Allow,Deny
Deny from All
</Files>
– Dracorat 27 September 2012 в 17:53