防止直接访问 php 包含文件
我有一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
将其添加到您只想包含的页面,
然后在包含它的页面上添加
Add this to the page that you want to only be included
then on the pages that include it add
对于一般的“在您可能完全控制或不完全控制的 Apache 服务器上运行的 PHP 应用程序”情况,最简单的方法是将您的包含文件放入一个目录中,并拒绝访问 .htaccess 文件中的该目录。 为了省去人们谷歌搜索的麻烦,如果您使用 Apache,请将其放入您不希望访问的目录中名为“.htaccess”的文件中:
如果您实际上完全控制了服务器(更常见的是这些即使对于小应用程序来说,比我第一次写这个答案时还要好几天),最好的方法是将您想要保护的文件粘贴到您的网络服务器所提供服务的目录之外。 因此,如果您的应用程序位于
/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:
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.,在包含该文件时与直接访问该文件时需要采取不同的行为(主要是
print()
与return()
),以下是一些修改后的代码:我有一个文件 被访问的始终是包含文件,因此 == 1。
I have a file that I need to act differently when it's included vs when it's accessed directly (mainly a
print()
vsreturn()
) Here's some modified code:The file being accessed is always an included file, hence the == 1.
防止直接访问文件的最佳方法是将它们放置在 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.
1:检查包含文件的数量
逻辑:如果未达到最小包含数量,PHP 将退出。 请注意,在 PHP5 之前,基页不被视为包含。
2:定义并验证全局常量
逻辑: 如果没有定义该常量,则不会从基页开始执行,PHP 将停止执行。
注意,为了跨升级和未来更改的可移植性,使此身份验证方法模块化将显着减少编码开销,因为更改不需要硬编码到每个文件.
这样可以将额外的代码添加到
checkdefine.php
用于日志记录和分析目的,以及生成适当的响应。 >应有的信用:可移植性的绝妙想法来自这个答案 。 然而这种方法有一个缺点。 不同文件夹中的文件可能需要不同的地址来寻址该文件。 如果您从主站点的子文件夹中运行当前网站,基于服务器根的寻址可能不起作用。
3:远程地址授权
此方法的缺点是隔离执行,除非提供了会话令牌内部请求。 在单服务器配置的情况下通过环回地址进行验证,或者在多服务器或负载平衡服务器基础设施的情况下通过地址白名单进行验证。
4:令牌授权
与上一种方法类似,可以使用 GET 或 POST 将授权令牌传递到包含文件:
一种非常混乱的方法,但如果以正确的方式使用,同时也可能是最安全和通用的方法。
5:Web 服务器特定配置
大多数服务器允许您为单个文件或目录分配权限。 您可以将所有包含内容放入此类受限目录中,并将服务器配置为拒绝它们。
例如,在 APACHE 中,配置存储在
.htaccess
文件中。 教程此处。请注意,但是我不推荐特定于服务器的配置,因为它们不利于跨不同 Web 服务器的可移植性。 在内容管理系统等拒绝算法复杂或拒绝目录列表相当大的情况下,它可能只会使重新配置会话变得相当可怕。 最后,最好在代码中处理这个问题。
6:将包含内容放在站点根目录之外的安全目录中
由于服务器环境中的访问限制,这是最不推荐的,但如果您有权访问该文件,则这是一个相当强大的方法 -系统。
逻辑:
htdocs
文件夹之外的任何文件,因为链接超出了网站地址系统的范围。请原谅我的非正统编码约定。 如有任何反馈,我们将不胜感激。
1: Checking the count of included files
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
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.
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
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:
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.
Logic:
htdocs
folder as the links would be outside the scope of the website's address system.Please excuse my unorthodox coding conventions. Any feedback is appreciated.
Chuck 解决方案的替代(或补充)是通过在 .htaccess 文件中放入类似的内容来拒绝访问与特定模式匹配的文件
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
实际上我的建议是采用所有这些最佳实践。
并且
这样,如果文件因某种原因放错位置(错误的 ftp 操作),它们仍然受到保护。
Actually my advice is to do all of these best practices.
AND
This way if the files become misplaced somehow (an errant ftp operation) they are still protected.
我曾经遇到过这个问题,解决方法是:
但理想的解决方案是将文件放置在网络服务器文档根目录之外,如另一个 anwser 中提到的。
I had this problem once, solved with:
but the ideal solution is to place the file outside of the web-server document root, as mentioned in another anwser.
我想限制直接访问 PHP 文件,但也能够通过
jQuery $.ajax (XMLHttpRequest)
调用它。 这对我有用。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.您最好构建具有一个入口点的应用程序,即所有文件都应从index.php到达将
其放入index.php
此检查应在每个链接文件中运行(通过require或include)
You'd better build application with one entrance point, i.e. all files should be reached from index.php
Place this in index.php
This check should run in each linked file (via require or include)
我的答案在方法上有些不同,但包含了此处提供的许多答案。 我建议采用多管齐下的方法:
define('_SOMECONSTANT') or die('Hackers! Be gone!');
HOWEVER
定义或死亡
方法有许多缺点。 首先,测试和调试的假设确实很痛苦。 其次,如果你改变主意,它会涉及到可怕的、令人麻木的、无聊的重构。 “查找和替换!” 你说。 是的,但是你怎么确定到处都写得一模一样,嗯? 现在将其乘以数千个文件... oO然后就是 .htaccess。 如果您的代码分发到管理员不那么谨慎的网站上,会发生什么? 如果您仅依靠 .htaccess 来保护您的文件,您还需要 a) 备份,b) 一盒纸巾来擦干眼泪,c) 一个灭火器来扑灭来自人们的所有仇恨邮件中的火焰使用你的代码。
所以我知道这个问题要求“最简单”,但我认为这需要更多的“防御性编码”。
我的建议是:
require('ifyoulieyougonnadie.php');
(不是include()
并作为替换已定义或死亡
)在
ifyoulieyougonnadie.php
中,执行一些逻辑操作 - 检查不同的常量、调用脚本、本地主机测试等 - 然后实现您的die()、抛出新异常、403
等我正在创建自己的框架,有两个可能的入口点 - 主index.php(Joomla框架)和ajaxrouter.php(我的框架) - 因此根据入口点,我检查不同的东西。 如果对
ifyoulieyougonnadie.php
的请求不是来自这两个文件之一,我就知道有人在搞恶作剧!但是如果我添加一个新的入口点怎么办? 不用担心。 我只需更改
ifyoulieyougonnadie.php
即可进行排序,并且没有“查找和替换”。 万岁!如果我决定将一些脚本移至不具有相同常量
define()
的不同框架,该怎么办? ...万岁! ^_^我发现这个策略使开发变得更有趣,而且更少:
My answer is somewhat different in approach but includes many of the answers provided here. I would recommend a multipronged approach:
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.OAnd 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:
require('ifyoulieyougonnadie.php');
(notinclude()
and as a replacement fordefined or die
)In
ifyoulieyougonnadie.php
, do some logic stuff - check for different constants, calling script, localhost testing and such - and then implement yourdie(), 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:
最简单的方法是在调用 include 的文件中设置一些变量,例如
然后在要包含的文件中检查该变量
The easiest way is to set some variable in the file that calls include, such as
Then in the file that's being included, check for the variable
除了 .htaccess 方式之外,我还在各种框架中看到了有用的模式,例如 ruby on Rails。 它们在应用程序根目录中有一个单独的 pub/ 目录,并且库目录位于与 pub/同一级别的目录中。 像这样的东西(不理想,但你明白了):
你设置你的网络服务器使用 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):
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.
什么Joomla! 所做的就是在根文件中定义一个常量,并检查包含的文件中是否定义了相同的常量。
或者,
可以按照大多数框架(如 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.
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.
如果更准确地说,您应该使用以下条件:
get_included_files()返回包含所有包含文件的名称的索引数组(如果文件被执行,则它被包含并且其名称在数组中)。
因此,当直接访问文件时,它的名称是数组中的第一个,数组中的所有其他文件都包括在内。
If more precisely, you should use this condition:
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.
将包含文件存储在可访问的 Web 目录之外已经被提到过几次,并且在可能的情况下当然是一个很好的策略。 然而,我还没有看到提到的另一个选项:确保您的包含文件不包含任何可运行的代码。 如果您的包含文件仅定义函数和类,并且除此之外没有任何代码,那么直接访问它们时只会产生一个空白页。
无论如何,允许从浏览器直接访问此文件:它不会执行任何操作。 它定义了一些函数,但没有调用它们,因此它们都没有运行。
这同样适用于仅包含 PHP 类而不包含其他内容的文件。
尽可能将文件保留在 Web 目录之外仍然是一个好主意。
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.
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.
system
, because that would conflict with a path used for code. I find this annoying.做类似的事情:
Do something like:
将上面的代码放在包含的 php 文件的顶部。
前任:
place the code above in the top of your included php file.
ex:
以下代码用于 Flatnux CMS (http://flatnux.altervista.org):
The following code is used in the Flatnux CMS (http://flatnux.altervista.org):
我发现这个仅适用于 http 和 cli 的不变解决方案:
定义一个函数:
在要阻止直接访问的文件中调用该函数:
上面给出的针对此问题的大多数解决方案在 Cli 模式下不起作用。
I found this php-only and invariable solution which works both with http and cli :
Define a function :
Call the function in the file you want to prevent direct access to :
Most of the solutions given above to this question do not work in Cli mode.
您可以使用下面的方法,但它确实有一个缺陷,因为它可以被伪造,除非您可以使用 Javascript 添加另一行代码来确保请求仅来自您的服务器。
您可以将此代码放在 HTML 代码的正文部分中,以便错误显示在那里。
将您的其他 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.
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.
出于安全原因,我建议不要使用
$_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.您还可以做的是用密码保护目录并将所有 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
最简单的方法是将包含内容存储在 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.
我发现 .htaccess 的建议不太好,因为它可能会阻塞
您可能希望允许用户访问该文件夹中的其他内容,
这是我的解决方案:
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:
前面提到的添加了 PHP 版本检查的解决方案:
Earlier mentioned solution with PHP version check added:
您可以使用 phpMyAdmin 样式:
You can use phpMyAdmin Style: