如何知道php脚本是否通过require_once()调用?

ala*_*boy 2 php require-once

我的webapp有很多模块.每个模块都有一个'main'php脚本,它根据发送到主模块的查询加载子模块:

//file: clientes.php

//check for valid user...
//import CSS and JS...

switch( $_GET["action"] )
{
    case "lista" :          require_once("clientes.lista.php"); break;
    case "listaDeudores" :  require_once("clientes.listaDeudores.php"); break;
    case "nuevo" :          require_once("clientes.nuevo.php"); break;
    case "detalles" :       require_once("clientes.detalles.php"); break;
    case "editar" :         require_once("clientes.editar.php"); break;         
    default : echo "<h1>Error</h1><p>El sitio ha encontrado un error.</p>";
} 
Run Code Online (Sandbox Code Playgroud)

该主要模块处理安全性并导入所有子模块所需的许多资源.当用户请求任何子模块时,会出现一个大问题,绕过主模块上的所有安全措施!我的想法是在每个子模块上添加一行来测试它是否被直接调用并拒绝访问,或者是否通过另一个脚本调用它,并继续.我想做的最少的事情是重做每个文件的安全检查,因为它对数据库进行了大量的查询.

php脚本是否知道是通过require_once()直接调用还是直接调用?我一直在试图实现某种$_SERVER['REQUEST_URI']$_SERVER['PHP_SELF']陷阱,但我不知道是否有某种这样的一种优雅的方式.

小智 17

我正在寻找一种方法来确定文件是否已被包含或直接调用,所有这些都来自文件.在我的任务的某个时刻,我通过了这个线程.检查PHP手册中这个和其他网站和页面上的各种其他线程我得到了启发,并提出了这段代码:

if ( basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"]) ) {
  echo "called directly";
}

else {
  echo "included/required"
}
Run Code Online (Sandbox Code Playgroud)

实质上,它会比较当前文件的名称(可以包含的文件的名称)是否与正在执行的文件相同.


说明:

  • __FILE__是一个PHP魔术常量,它存储文件的完整路径和文件名,它的美妙之处在于,如果文件已被包含或需要,它仍会返回此类文件的完整路径和文件名(包含的文件).
    (Magic Constants Manual:http://php.net/manual/en/language.constants.predefined.php)

  • $ _SERVER ["SCRIPT_FILENAME"]返回当前正在执行的脚本的绝对路径名.当包含/需要文件时,它不会被执行(只是包含),它返回(比如说)"父"文件的路径名(包含另一个文件的文件和执行的文件).

  • basename(string $ path)是一个返回path的尾随名称组件的函数,在本例中是文件名.你也可以只比较完整的路径和文件名,这确实会更好,使用这个功能并不是真的很好,但是这种方式感觉更干净,jajaj.
    (basename():http://php.net/manual/en/function.basename.php)

我知道回答主要问题是一个"有点"的迟到,但我猜想,对于那些和我一样的情况并且也经过的人来说,这可能是有用的.


reg*_*ero 13

一种优雅的方法是将所有文件放在Web目录之外,只能通过include访问.

假设您的web目录是/ foo/www /,创建一个包含目录/ foo/includes并在include_path中设置它:

$root = '/foo';
$webroot = $root.'/www'; // in case you need it on day
$lib = $root.'/includes';
// this add your library at the end of the current include_path
set_include_path(get_include_path() . PATH_SEPARATOR . $lib); 
Run Code Online (Sandbox Code Playgroud)

然后,没有人能够直接访问您的库.

你可以做很多其他事情(设置测试全局变量,只使用库中的类等),但这个是最安全的.您的DocumentRoot中没有的每个文件都无法通过URL访问.但这并不意味着PHP无法访问此文件(如果您没有为空,请检查您的open_basedir配置,以允许您的include dir).

您在web目录中真正需要的唯一文件是我们称之为bootstrap(index.php),具有良好的重写规则或良好的url管理,您可以将应用程序上的所有请求限制到此文件,这将是一个很好的安全起点.


Pek*_*ica 6

确保模块不直接调用的一种流行方法是在主脚本中定义一个常量,并在模块中检查该常量.

// index.php
define("LEGIT_REQUEST", true);

// in each module
if (!defined("LEGIT_REQUEST")) 
  die ("This module cannot be called directly.");
Run Code Online (Sandbox Code Playgroud)


Álv*_*lez 5

为了完整起见,另一种可能性是将这些文件移动到不公开的目录.但是,托管服务提供商使用的某些控制面板使这变得不可能 在这种情况下,如果您使用的是Apache,则可以.htaccess在目录中放置一个文件:

#
# Private directory
#
Order allow,deny
Deny from all
Run Code Online (Sandbox Code Playgroud)