【发布时间】:2011-01-24 17:12:08
【问题描述】:
有没有办法阻止用户查看文件但仍将其作为包含在PHP 中的另一个文件中使用?
【问题讨论】:
有没有办法阻止用户查看文件但仍将其作为包含在PHP 中的另一个文件中使用?
【问题讨论】:
如果你使用
define('APP_RAN');
在包含它的文件中,然后放入
if(!defined('APP_RAN')){ die(); }
或者
defined('APP_RAN') or die();
(更容易阅读)
在包含的文件中,如果你直接访问它们会死掉。
不过,最好将所有包含的文件放在 DocumentRoot 之上。
例如,如果您的索引页位于
/my/server/domain/public_html
你应该把包含的文件放进去
/my/server/domain/
【讨论】:
defined('APP_RAN') or die(); - 同意。样板文件应尽可能短。
我的建议:
<?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 部分避免在文件上传到实时环境时部分执行(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");
【讨论】:
if ( count(get_included_files()) === 1 ) die("Direct access forbidden");。
在 Apache 下,这很简单:在 .htaccess 中添加 <Files> 指令,以防止从 Web 浏览器访问它。这不适用于 PHP includes,最好隐藏多个文件以防止浏览器访问(尽管通常您会尝试将所有不可访问的文件放在一个目录中)。
<Files="myprivatefile.php">
deny from all
</Files>
在不同的网络服务器下,您可以将文件隐藏在文档根目录之外,但在某些情况下(例如,如果您的脚本严格使用 open_basedir'd),它将不起作用。
【讨论】:
检查有多少包含的文件...
if(count(get_required_files()) < 2) { die(); }
或者应该有多少个最小值而不是 2 个
【讨论】:
如果您想阻止它在未包含时显示,这里有一种更自动化的方法。
if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])) header("HTTP/1.0 404 Not Found");
这样,如果您最终更改文件名或其他内容,它仍然可以工作。
【讨论】:
if($argv[0] == basename(__FILE__))
include_once('/path/to/file.php');
【讨论】:
这个帖子中有很多很好的答案 - 这里有一个尚未提及。
您可以在扩展名中使用i 命名包含的 PHP 文件,例如someincludedfile.phpi 然后配置 Apache 使其不提供 phpi 文件。瞧。
缺点:
优点:
就个人而言,我宁愿只是将文件移动到文档根目录之外的目录中,但如果您有一个大型遗留应用程序,这可能会更快地更改。
链接:http://www.ducea.com/2006/07/21/apache-tips-tricks-deny-access-to-certain-file-types/
【讨论】:
我会选择Chacha102's solution。
此外,正如您的问题标题所说的“如何检查”,您也可以这样做而无需使用
定义变量// secret.php is the name of this file.
if($_SERVER["SCRIPT_FILENAME"]=='secret.php') die();
【讨论】:
只是用$_SERVER 变量扩展解决方案 - 下面是一个小的 .php 文件,在 cmets 中是我在 Ubuntu 上进行的bash 测试的副本;关键是,这些变量可能会根据访问类型以及是否使用符号链接而发生很大变化(还要注意,在下面的代码中,我必须在 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
*/
?>
【讨论】: