如何检测文件是否被包含或直接运行

时间:2011-04-26 22:21:20

标签: php include

我有一个php文件,我包含在我的PHP脚本中,但我不希望人们能够直接运行该文件(不包括在内)。 我该如何防止这种情况发生?

6 个答案:

答案 0 :(得分:5)

使所包含的脚本无法通过HTTP访问。例如。通过保护子文件夹或将其移动到文档根目录之上。

如果你不能这样做,define()主要脚本中的IS_INCLUDEDexit;之类的内容,如果此常量不是defined()

答案 1 :(得分:4)

检查脚本是否是PHP进程的父进程可能不是阻止用户直接请求包含文件的最佳选择。但它在许多其他情况下都很方便,即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()是你的朋友。

答案 2 :(得分:3)

我使用“包含”脚本中定义的 sentinel constant ,“included”脚本查找它。

示例:

/* main.php */
define('SENTINEL', 1);
include "included.inc.php"

/* included.inc.php */
if (!defined('SENTINEL')) die("Wanted to be smart?? Nice try.");

答案 3 :(得分:2)

2个提供良好保护的解决方案:

  1. 的Apache
  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

    1. PHP
    2. 使用此示例代码,PHP能够检测到include:

      if( get_included_files()[0] == __FILE__ ){
          echo '2.php direct access';
      }else{
          echo '2.php was included';
      }
      

      修改: 请参阅Tim回答,所以如果你有一个prepend 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";
      

答案 4 :(得分:1)

我在某些应用程序中看到过这种模式:

  1. 主要,直接运行文件define('SOMETHING', 'SOMEVALUE');
  2. 包含的文件以if(!defined('SOMETHING')) return;
  3. 开头

答案 5 :(得分:0)

包含的PHP文件应包含类/函数/变量定义,而不是内联逻辑/输出。

基本上,直接运行它们是一种无操作。