防止直接访问 php 包含文件

发布于 2024-07-11 21:08:37 字数 243 浏览 9 评论 0原文

我有一个 php 文件,我将专门将其用作包含文件。 因此,当通过输入 URL 直接访问而不是包含在内时,我想抛出一个错误而不是执行它。

基本上我需要在 php 文件中进行如下检查:

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

有没有一种简单的方法可以做到这一点?

I have a php file which I will be using as exclusively as an include. Therefore I would like to throw an error instead of executing it when it's accessed directly by typing in the URL instead of being included.

Basically I need to do a check as follows in the php file:

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

Is there an easy way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

萝莉病 2024-07-18 21:08:37

将其添加到您只想包含的页面,

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

然后在包含它的页面上添加

<?php
define('MyConst', TRUE);
?>

Add this to the page that you want to only be included

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

then on the pages that include it add

<?php
define('MyConst', TRUE);
?>
顾北清歌寒 2024-07-18 21:08:37

对于一般的“在您可能完全控制或不完全控制的 Apache 服务器上运行的 PHP 应用程序”情况,最简单的方法是将您的包含文件放入一个目录中,并拒绝访问 .htaccess 文件中的该目录。 为了省去人们谷歌搜索的麻烦,如果您使用 Apache,请将其放入您不希望访问的目录中名为“.htaccess”的文件中:

Deny from all

如果您实际上完全控制了服务器(更常见的是这些即使对于小应用程序来说,比我第一次写这个答案时还要好几天),最好的方法是将您想要保护的文件粘贴到您的网络服务器所提供服务的目录之外。 因此,如果您的应用程序位于 /srv/YourApp/ 中,请将服务器设置为从 /srv/YourApp/app/ 提供文件,并将包含内容放入 /srv /YourApp/includes,因此实际上没有任何 URL 可以访问它们。

The easiest way for the generic "PHP app running on an Apache server that you may or may not fully control" situation is to put your includes in a directory and deny access to that directory in your .htaccess file. To save people the trouble of Googling, if you're using Apache, put this in a file called ".htaccess" in the directory you don't want to be accessible:

Deny from all

If you actually have full control of the server (more common these days even for little apps than when I first wrote this answer), the best approach is to stick the files you want to protect outside of the directory that your web server is serving from. So if your app is in /srv/YourApp/, set the server to serve files from /srv/YourApp/app/ and put the includes in /srv/YourApp/includes, so there literally isn't any URL that can access them.

一江春梦 2024-07-18 21:08:37

,在包含该文件时与直接访问该文件时需要采取不同的行为(主要是 print()return()),以下是一些修改后的代码:

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

我有一个文件 被访问的始终是包含文件,因此 == 1。

I have a file that I need to act differently when it's included vs when it's accessed directly (mainly a print() vs return()) Here's some modified code:

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

The file being accessed is always an included file, hence the == 1.  

空城之時有危險 2024-07-18 21:08:37

防止直接访问文件的最佳方法是将它们放置在 Web 服务器文档根目录之外(通常是上面一层)。 您仍然可以包含它们,但其他人不可能通过 http 请求访问它们。

我通常会一路走下去,并将所有 PHP 文件放在文档根目录之外,除了 引导文件 - 文档根目录中的一个单独的index.php,用于开始路由整个网站/应用程序。

The best way to prevent direct access to files is to place them outside of the web-server document root (usually, one level above). You can still include them, but there is no possibility of someone accessing them through an http request.

I usually go all the way, and place all of my PHP files outside of the document root aside from the bootstrap file - a lone index.php in the document root that starts routing the entire website/application.

顾铮苏瑾 2024-07-18 21:08:37

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 将停止执行。

注意,为了跨升级和未来更改的可移植性,使此身份验证方法模块化将显着减少编码开销,因为更改不需要硬编码到每个文件.

// Put the code in a separate file instead, say 'checkdefined.php':
defined('_DEFVAR') or exit('Restricted Access');

// Replace the same code in the include files with:
require_once('checkdefined.php');

这样可以将额外的代码添加到 checkdefine.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:Web 服务器特定配置

大多数服务器允许您为单个文件或目录分配权限。 您可以将所有包含内容放入此类受限目录中,并将服务器配置为拒绝它们。

例如,在 APACHE 中,配置存储在 .htaccess 文件中。 教程此处

请注意,但是我不推荐特定于服务器的配置,因为它们不利于跨不同 Web 服务器的可移植性。 在内容管理系统等拒绝算法复杂或拒绝目录列表相当大的情况下,它可能只会使重新配置会话变得相当可怕。 最后,最好在代码中处理这个问题。


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 服务器可以访问它们,同时拒绝用户进行热链接。
  • 即使网络服务器的文件系统访问配置没有正确完成,此方法也可以防止这些文件意外公开。

请原谅我的非正统编码约定。 如有任何反馈,我们将不胜感激。

1: Checking the count of included files

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

Logic: PHP exits if the minimum include count isn't met. Note that prior to PHP5, the base page is not considered an include.


2: Defining and verifying a global constant

// 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');

Logic: If the constant isn't defined, then the execution didn't start from the base page, and PHP would stop executing.

Note that for the sake of portability across upgrades and future changes, making this authentication method modular would significantly reduce the coding overhead as the changes won't need to be hard-coded to every single file.

// Put the code in a separate file instead, say 'checkdefined.php':
defined('_DEFVAR') or exit('Restricted Access');

// Replace the same code in the include files with:
require_once('checkdefined.php');

This way additional code can be added to checkdefined.php for logging and analytical purposes, as well as for generating appropriate responses.

Credit where credit is due: The brilliant idea of portability came from this answer. However there is one con to this method. Files in different folders may require different addresses to address this file. And server root based addressing may not work if you're running the current website from within a subfolder of the main site.


3: Remote address authorisation

// 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');

The drawback with this method is isolated execution, unless a session-token provided with the internal request. Verify via the loop-back address in case of a single server configuration, or an address white-list for a multi-server or load-balanced server infrastructure.


4: Token authorisation

Similar to the previous method, one can use GET or POST to pass an authorization token to the include file:

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

A very messy method, but also perhaps the most secure and versatile at the same time, when used in the right way.


5: Webserver specific configuration

Most servers allow you to assign permissions for individual files or directories. You could place all your includes in such restricted directories, and have the server configured to deny them.

For example in APACHE, the configuration is stored in the .htaccess file. Tutorial here.

Note however that server-specific configurations are not recommended by me because they are bad for portability across different web-servers. In cases like Content Management Systems where the deny-algorithm is complex or the list of denied directories is rather big, it might only make reconfiguration sessions rather gruesome. In the end it's best to handle this in code.


6: Placing includes in a secure directory OUTSIDE the site root

Least preferred because of access limitations in server environments, but a rather powerful method if you have access to the file-system.

//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");

Logic:

  • The user cannot request any file outside the htdocs folder as the links would be outside the scope of the website's address system.
  • The php server accesses the file-system natively, and hence can access files on a computer just like how a normal program with required privileges can.
  • By placing the include files in this directory, you can ensure that the php server gets to access them, while hotlinking is denied to the user.
  • Even if the webserver's filesystem access configuration wasn't done properly, this method would prevent those files from becoming public accidentally.

Please excuse my unorthodox coding conventions. Any feedback is appreciated.

苏大泽ㄣ 2024-07-18 21:08:37

Chuck 解决方案的替代(或补充)是通过在 .htaccess 文件中放入类似的内容来拒绝访问与特定模式匹配的文件

<FilesMatch "\.(inc)$">
    Order deny,allow
    Deny from all
</FilesMatch>

An alternative (or complement) to Chuck's solution would be to deny access to files matching a specific pattern by putting something like this in your .htaccess file

<FilesMatch "\.(inc)$">
    Order deny,allow
    Deny from all
</FilesMatch>
冷默言语 2024-07-18 21:08:37

实际上我的建议是采用所有这些最佳实践。

  • 将文档放在网络根目录之外或网络服务器拒绝访问的目录中
    并且
  • 在可见文档中使用隐藏文档检查的定义:
      if (!defined(INCL_FILE_FOO)) {
          header('HTTP/1.0 403 Forbidden');
          exit;
      }

这样,如果文件因某种原因放错位置(错误的 ftp 操作),它们仍然受到保护。

Actually my advice is to do all of these best practices.

  • Put the documents outside the webroot OR in a directory denied access by the webserver
    AND
  • Use a define in your visible documents that the hidden documents check for:
      if (!defined(INCL_FILE_FOO)) {
          header('HTTP/1.0 403 Forbidden');
          exit;
      }

This way if the files become misplaced somehow (an errant ftp operation) they are still protected.

故笙诉离歌 2024-07-18 21:08:37

我曾经遇到过这个问题,解决方法是:

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

但理想的解决方案是将文件放置在网络服务器文档根目录之外,如另一个 anwser 中提到的。

I had this problem once, solved with:

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

but the ideal solution is to place the file outside of the web-server document root, as mentioned in another anwser.

司马昭之心 2024-07-18 21:08:37

我想限制直接访问 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;
    }
}

I wanted to restrict access to the PHP file directly, but also be able to call it via jQuery $.ajax (XMLHttpRequest). Here is what worked for me.

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;
    }
}
高跟鞋的旋律 2024-07-18 21:08:37

您最好构建具有一个入口点的应用程序,即所有文件都应从index.php到达将

其放入index.php

define(A,true);

此检查应在每个链接文件中运行(通过require或include)

defined('A') or die(header('HTTP/1.0 403 Forbidden'));

You'd better build application with one entrance point, i.e. all files should be reached from index.php

Place this in index.php

define(A,true);

This check should run in each linked file (via require or include)

defined('A') or die(header('HTTP/1.0 403 Forbidden'));
荒人说梦 2024-07-18 21:08:37
debug_backtrace() || die ("Direct access not permitted");
debug_backtrace() || die ("Direct access not permitted");
一个人练习一个人 2024-07-18 21:08:37

我的答案在方法上有些不同,但包含了此处提供的许多答案。 我建议采用多管齐下的方法:

  1. .htaccess 和 Apache 限制肯定是
  2. define('_SOMECONSTANT') or die('Hackers! Be gone!');

HOWEVER 定义或死亡方法有许多缺点。 首先,测试和调试的假设确实很痛苦。 其次,如果你改变主意,它会涉及到可怕的、令人麻木的、无聊的重构。 “查找和替换!” 你说。 是的,但是你怎么确定到处都写得一模一样,嗯? 现在将其乘以数千个文件... oO

然后就是 .htaccess。 如果您的代码分发到管理员不那么谨慎的网站上,会发生什么? 如果您仅依靠 .htaccess 来保护您的文件,您还需要 a) 备份,b) 一盒纸巾来擦干眼泪,c) 一个灭火器来扑灭来自人们的所有仇恨邮件中的火焰使用你的代码。

所以我知道这个问题要求“最简单”,但我认为这需要更多的“防御性编码”。

我的建议是:

  1. 在任何脚本之前 require('ifyoulieyougonnadie.php');不是 include() 并作为替换已定义或死亡)
  2. ifyoulieyougonnadie.php中,执行一些逻辑操作 - 检查不同的常量、调用脚本、本地主机测试等 - 然后实现您的 die()、抛出新异常、403

    我正在创建自己的框架,有两个可能的入口点 - 主index.php(Joomla框架)和ajaxrouter.php(我的框架) - 因此根据入口点,我检查不同的东西。 如果对 ifyoulieyougonnadie.php 的请求不是来自这两个文件之一,我就知道有人在搞恶作剧!

    但是如果我添加一个新的入口点怎么办? 不用担心。 我只需更改 ifyoulieyougonnadie.php 即可进行排序,并且没有“查找和替换”。 万岁!

    如果我决定将一些脚本移至不具有相同常量 define() 的不同框架,该怎么办? ...万岁! ^_^

我发现这个策略使开发变得更有趣,而且更少:

/**
 * 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();

My answer is somewhat different in approach but includes many of the answers provided here. I would recommend a multipronged approach:

  1. .htaccess and Apache restrictions for sure
  2. defined('_SOMECONSTANT') or die('Hackers! Be gone!');

HOWEVER the defined or die approach has a number of failings. Firstly, it is a real pain in the assumptions to test and debug with. Secondly, it involves horrifyingly, mind-numbingly boring refactoring if you change your mind. "Find and replace!" you say. Yes, but how sure are you that it is written exactly the same everywhere, hmmm? Now multiply that with thousands of files... o.O

And then there's .htaccess. What happens if your code is distributed onto sites where the administrator is not so scrupulous? If you rely only on .htaccess to secure your files you're also going to need a) a backup, b) a box of tissues to dry your tears, c) a fire extinguisher to put out the flames in all the hatemail from people using your code.

So I know the question asks for the "easiest", but I think what this calls for is more "defensive coding".

What I suggest is:

  1. Before any of your scripts require('ifyoulieyougonnadie.php'); (not include() and as a replacement for defined or die)
  2. In ifyoulieyougonnadie.php, do some logic stuff - check for different constants, calling script, localhost testing and such - and then implement your die(), throw new Exception, 403, etc.

    I am creating my own framework with two possible entry points - the main index.php (Joomla framework) and ajaxrouter.php (my framework) - so depending on the point of entry, I check for different things. If the request to ifyoulieyougonnadie.php doesn't come from one of those two files, I know shenanigans are being undertaken!

    But what if I add a new entry point? No worries. I just change ifyoulieyougonnadie.php and I'm sorted, plus no 'find and replace'. Hooray!

    What if I decided to move some of my scripts to do a different framework that doesn't have the same constants defined()? ... Hooray! ^_^

I found this strategy makes development a lot more fun and a lot less:

/**
 * 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();
太阳公公是暖光 2024-07-18 21:08:37

最简单的方法是在调用 include 的文件中设置一些变量,例如

$including = true;

然后在要包含的文件中检查该变量

if (!$including) exit("direct access not permitted");

The easiest way is to set some variable in the file that calls include, such as

$including = true;

Then in the file that's being included, check for the variable

if (!$including) exit("direct access not permitted");
无边思念无边月 2024-07-18 21:08:37

除了 .htaccess 方式之外,我还在各种框架中看到了有用的模式,例如 ruby​​ on Rails。 它们在应用程序根目录中有一个单独的 pub/ 目录,并且库目录位于与 pub/同一级别的目录中。 像这样的东西(不理想,但你明白了):

app/
 |
 +--pub/
 |
 +--lib/
 |
 +--conf/
 |
 +--models/
 |
 +--views/
 |
 +--controllers/

你设置你的网络服务器使用 pub/ 作为文档根目录。 这为您的脚本提供了更好的保护:虽然它们可以从文档根目录加载必要的组件,但无法从互联网访问这些组件。 除了安全性之外的另一个好处是一切都集中在一个地方。

此设置比仅在每个包含的文件中创建检查更好,因为“不允许访问”消息是攻击者的线索,并且它比 .htaccess 配置更好,因为它不是基于白名单的:如果您搞砸了文件扩展名它在 lib/、conf/ 等目录中不可见。

Besides the .htaccess way, I have seen a useful pattern in various frameworks, for example in ruby on rails. They have a separate pub/ directory in the application root directory and the library directories are living in directories at the same level as pub/. Something like this (not ideal, but you get the idea):

app/
 |
 +--pub/
 |
 +--lib/
 |
 +--conf/
 |
 +--models/
 |
 +--views/
 |
 +--controllers/

You set up your web server to use pub/ as document root. This offers better protection to your scripts: while they can reach out from the document root to load necessary components it is impossible to access the components from the internet. Another benefit besides security is that everything is in one place.

This setup is better than just creating checks in every single included file because "access not permitted" message is a clue to attackers, and it is better than .htaccess configuration because it is not white-list based: if you screw up the file extensions it will not be visible in the lib/, conf/ etc. directories.

庆幸我还是我 2024-07-18 21:08:37

什么Joomla! 所做的就是在根文件中定义一个常量,并检查包含的文件中是否定义了相同的常量。

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

或者,

可以按照大多数框架(如 CodeIgniter)的建议,将所有文件放置在 webroot 目录之外,从而将所有文件置于 http 请求范围之外。

或者甚至通过在包含文件夹中放置 .htaccess 文件并编写规则,您可以防止直接访问。

What Joomla! does is defining a Constant in a root file and checking if the same is defined in the included files.

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

or else

one can keep all files outside the reach of an http request by placing them outside the webroot directory as most frameworks like CodeIgniter recommend.

or even by placing an .htaccess file within the include folder and writing rules, you can prevent direct access.

迷路的信 2024-07-18 21:08:37
<?php       
$url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
  if (false !== strpos($url,'.php')) {
      die ("Direct access not premitted");
  }
?>
<?php       
$url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
  if (false !== strpos($url,'.php')) {
      die ("Direct access not premitted");
  }
?>
離人涙 2024-07-18 21:08:37

如果更准确地说,您应该使用以下条件:

if (array_search(__FILE__, get_included_files()) === 0) {
    echo 'direct access';
}
else {
    echo 'included';
}

get_included_files()返回包含所有包含文件的名称的索引数组(如果文件被执行,则它被包含并且其名称在数组中)。
因此,当直接访问文件时,它的名称是数组中的第一个,数组中的所有其他文件都包括在内。

If more precisely, you should use this condition:

if (array_search(__FILE__, get_included_files()) === 0) {
    echo 'direct access';
}
else {
    echo 'included';
}

get_included_files() returns indexed array containing names of all included files (if file is beign executed then it was included and its name is in the array).
So, when the file is directly accessed, its name is the first in the array, all other files in the array were included.

寂寞美少年 2024-07-18 21:08:37

将包含文件存储在可访问的 Web 目录之外已经被提到过几次,并且在可能的情况下当然是一个很好的策略。 然而,我还没有看到提到的另一个选项:确保您的包含文件不包含任何可运行的代码。 如果您的包含文件仅定义函数和类,并且除此之外没有任何代码,那么直接访问它们时只会产生一个空白页。

无论如何,允许从浏览器直接访问此文件:它不会执行任何操作。 它定义了一些函数,但没有调用它们,因此它们都没有运行。

<?php

function a() {
    // function body
}

function b() {
    // function body
}

这同样适用于仅包含 PHP 类而不包含其他内容的文件。


尽可能将文件保留在 Web 目录之外仍然是一个好主意。

  • 您可能会意外停用 PHP,在这种情况下,您的服务器可能会将 PHP 文件的内容发送到浏览器,而不是运行 PHP 并发送结果。 这可能会导致您的代码(包括数据库密码、API 密钥等)泄露。
  • Web 目录中的文件占用了您可能想要用于应用程序的 URL。 我使用的 CMS 不能有名为 system 的页面,因为这会与代码使用的路径冲突。 我觉得这很烦人。

Storing your include files outside the web accessible directory has been mentioned a few times, and is certainly a good strategy where possible. However, another option I have not yet seen mentioned: ensure that your include files don’t contain any runnable code. If your include files merely define functions and classes, and have no code other than that, they will simply produce a blank page when accessed directly.

By all means allow direct access to this file from the browser: it won’t do anything. It defines some functions, but none of them are called, so none of them run.

<?php

function a() {
    // function body
}

function b() {
    // function body
}

The same applies to files which contain only PHP classes, and nothing else.


It’s still a good idea to keep your files outside of the web directory where possible.

  • You might accidentally deactivate PHP, in which case your server may send content of the PHP files to the browser, instead of running PHP and sending the result. This could result in your code (including database passwords, API keys, etc.) leaking.
  • Files in the web directory are squatting on URLs you may want to use for your app. I work with a CMS which cannot have a page called system, because that would conflict with a path used for code. I find this annoying.
一场信仰旅途 2024-07-18 21:08:37

做类似的事情:

<?php
if ($_SERVER['SCRIPT_FILENAME'] == '<path to php include file>') {
    header('HTTP/1.0 403 Forbidden');
    exit('Forbidden');
}
?>

Do something like:

<?php
if ($_SERVER['SCRIPT_FILENAME'] == '<path to php include file>') {
    header('HTTP/1.0 403 Forbidden');
    exit('Forbidden');
}
?>
家住魔仙堡 2024-07-18 21:08:37
<?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 文件的顶部。

前任:

<?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
?>
<?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>");
}
?>

place the code above in the top of your included php file.

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
?>
信愁 2024-07-18 21:08:37

以下代码用于 Flatnux CMS (http://flatnux.altervista.org):

if ( strpos(strtolower($_SERVER['SCRIPT_NAME']),strtolower(basename(__FILE__))) )
{
    header("Location: ../../index.php");
    die("...");
}

The following code is used in the Flatnux CMS (http://flatnux.altervista.org):

if ( strpos(strtolower($_SERVER['SCRIPT_NAME']),strtolower(basename(__FILE__))) )
{
    header("Location: ../../index.php");
    die("...");
}
醉酒的小男人 2024-07-18 21:08:37

我发现这个仅适用于 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 模式下不起作用。

I found this php-only and invariable solution which works both with http and cli :

Define a function :

function forbidDirectAccess($file) {
    $self = getcwd()."/".trim($_SERVER["PHP_SELF"], "/");
    (substr_compare($file, $self, -strlen($self)) != 0) or die('Restricted access');
}

Call the function in the file you want to prevent direct access to :

forbidDirectAccess(__FILE__);

Most of the solutions given above to this question do not work in Cli mode.

甜中书 2024-07-18 21:08:37
if (basename($_SERVER['PHP_SELF']) == basename(__FILE__)) { die('Access denied'); };
if (basename($_SERVER['PHP_SELF']) == basename(__FILE__)) { die('Access denied'); };
眼眸 2024-07-18 21:08:37

您可以使用下面的方法,但它确实有一个缺陷,因为它可以被伪造,除非您可以使用 Javascript 添加另一行代码来确保请求仅来自您的服务器。
您可以将此代码放在 HTML 代码的正文部分中,以便错误显示在那里。

<?
if(!isset($_SERVER['HTTP_REQUEST'])) { include ('error_file.php'); }
else { ?>

将您的其他 HTML 代码放在这里

<? } ?>

并像这样结束它,这样错误的输出将始终显示在正文部分中(如果您希望如此)。

You can use the following method below although, it does have a flaw, because it can be faked, except if you can add another line of code to make sure the request comes only from your server either by using Javascript.
You can place this code in the Body section of your HTML code, so the error shows there.

<?
if(!isset($_SERVER['HTTP_REQUEST'])) { include ('error_file.php'); }
else { ?>

Place your other HTML code here

<? } ?>

End it like this, so the output of the error will always show within the body section, if that's how you want it to be.

黑寡妇 2024-07-18 21:08:37

出于安全原因,我建议不要使用 $_SERVER
您可以在包含另一个文件的第一个文件中使用像 $root=true; 这样的变量。
并在包含的第二个文件的开头使用 isset($root) 。

i suggest that don't use of $_SERVER for security reasons .
You can use a variable like $root=true; in first file that included another one.
and use isset($root) in begin of second file that be included.

深居我梦 2024-07-18 21:08:37

您还可以做的是用密码保护目录并将所有 php 脚本保留在其中,当然除了 index.php 文件,因为在包含时不需要密码,因为只有 http 访问才需要密码。 它还会为您提供访问脚本的选项(如果您需要的话),因为您将拥有访问该目录的密码。 您将需要为目录设置 .htaccess 文件和 .htpasswd 文件来验证用户身份。

好吧,如果您觉得不需要正常访问这些文件,您也可以使用上面提供的任何解决方案,因为您始终可以通过 cPanel 等访问它们。

希望这会有所帮助

What you can also do is password protect the directory and keep all your php scripts in there, ofcourse except the index.php file, as at the time of include password won't be required as it will be required only for http access. what it will do is also provide you the option to access your scripts in case you want it as you will have password to access that directory. you will need to setup .htaccess file for the directory and a .htpasswd file to authenticate the user.

well, you can also use any of the solutions provided above in case you feel you don't need to access those files normally because you can always access them through cPanel etc.

Hope this helps

森林很绿却致人迷途 2024-07-18 21:08:37

最简单的方法是将包含内容存储在 Web 目录之外。 这样服务器就可以访问它们,但不能访问外部机器。 唯一的缺点是您需要能够访问服务器的这一部分。 优点是它不需要设置、配置或额外的代码/服务器压力。

The easiest way is to store your includes outside of the web directory. That way the server has access to them but no outside machine. The only down side is you need to be able to access this part of your server. The upside is it requires no set up, configuration, or additional code/server stress.

轻许诺言 2024-07-18 21:08:37

我发现 .htaccess 的建议不太好,因为它可能会阻塞
您可能希望允许用户访问该文件夹中的其他内容,
这是我的解决方案:

$currentFileInfo = pathinfo(__FILE__);
$requestInfo = pathinfo($_SERVER['REQUEST_URI']);
if($currentFileInfo['basename'] == $requestInfo['basename']){
    // direct access to file
}

I didn't find the suggestions with .htaccess so good because it may block
other content in that folder which you might want to allow user to access to,
this is my solution:

$currentFileInfo = pathinfo(__FILE__);
$requestInfo = pathinfo($_SERVER['REQUEST_URI']);
if($currentFileInfo['basename'] == $requestInfo['basename']){
    // direct access to file
}
失而复得 2024-07-18 21:08:37

前面提到的添加了 PHP 版本检查的解决方案:

    $max_includes = version_compare(PHP_VERSION, '5', '<') ? 0 : 1;
    if (count(get_included_files()) <= $max_includes)
    {
        exit('Direct access is not allowed.');
    }

Earlier mentioned solution with PHP version check added:

    $max_includes = version_compare(PHP_VERSION, '5', '<') ? 0 : 1;
    if (count(get_included_files()) <= $max_includes)
    {
        exit('Direct access is not allowed.');
    }
杀お生予夺 2024-07-18 21:08:37

您可以使用 phpMyAdmin 样式:

/**
 * block attempts to directly run this script
 */
if (getcwd() == dirname(__FILE__)) {
    die('Attack stopped');
}

You can use phpMyAdmin Style:

/**
 * block attempts to directly run this script
 */
if (getcwd() == dirname(__FILE__)) {
    die('Attack stopped');
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文