我设置了一台服务器,希望其中某个特定的 PHP 文件可以通过浏览器读取,但希望拒绝访问其余的 PHP 文件。因此,我将以下内容放在.htaccess
服务器根目录中:
<Files "*.php">
Require all denied
</Files>
然后,我将其放在子文件夹中(假设该文件夹为subdir
)以匹配特定文件:
<Files "folder/specific.php">
Require all granted
</Files>
但它不起作用。只有我直接输入以下内容才会起作用subdir/folder/specific.php
:
<Files "*.php">
Require all granted
</Files>
为什么会发生这种情况?即使我使用:
Order Allow, Deny
Allow from all
同样的事情也发生了。
答案1
<Files>
指令不应包含任何路径部分,而应包含基本文件名部分。指令的参数中不应包含斜杠,并且*
不匹配斜杠(顺便说一下,这在系统 shell 中通常有效)。core
模块文档状态:
本节中给出的指令将应用于基本名称(文件名的最后一个组件)与指定文件名匹配的任何对象。
显然,文件系统对象的基本名称(最后一个之后的内容/
)不能匹配包含斜杠的任何内容。
正如描述页面所建议的那样配置部分,为了匹配特定目录中的特定文件,通常嵌套<Files>
在相应的<Directory>
:
<Directory "/var/web/dir1">
<Files "private.html">
Require all denied
</Files>
</Directory>
这意味着错误的将其写为单个<Files "/var/web/dir1/private.html>
。就你的情况而言,我怀疑服务器应该在错误日志的某处抱怨.htaccess
有错误的指令。
由于.htaccess
不能包含<Directory>
部分并且其本身对应于放置它的目录路径,这意味着将您的<Files>
部分添加.htaccess
到放置在目标文件所在目录中的文件中(或其任何父级),而不使用指令中的任何路径。这正是您在“它仅有效”时所做的。
还请注意,.htaccess
文档 开始于:
.htaccess
如果您有权访问 httpd 主服务器配置文件,则应完全避免使用文件。使用.htaccess
文件会降低 Apache http 服务器的速度。任何可以包含在.htaccess
文件中的指令最好在目录块,因为它会达到同样的效果,但性能更佳。
所以仅有的它们提供的好处是能够在不访问服务器配置的情况下更改服务器的某些配置。其他一切都是可能的;如果您有这种访问权限(您肯定有,否则这里的问题就偏离主题了),您应该将您的 转换.haccess
为服务器内配置并禁用AllowOverride
,从而消除由此产生的任何性能损失。有关如何执行此操作的详细信息在同一页面的.htaccess
与主配置文件合并副标题。
答案2
继@Nikita Kipriyanov 的回答.htaccess
有一些替代方案,因为在子目录中创建额外的文件并不总是可取的、可能的,甚至是必要的。
如上所述,该<Files>
指令仅匹配文件名,而不匹配文件路径。它适用于包含该.htaccess
文件的目录及其所有子目录。
如果您希望授予访问权限的文件在文件.htaccess
适用的目录树中是“唯一的”,那么您不一定需要.htaccess
在该子目录中创建其他文件(这通常是不可取的),因为允许访问父/根文件中的文件名.htaccess
通常“足够好”。例如:
<Files "*.php">
Require all denied
</Files>
<Files "specific.php">
Require all granted
</Files>
可以使用正则表达式和负向前瞻将这两个<Files>
块组合成单个<FilesMatch>
指令。例如:
<FilesMatch ^(?!specific\.php).+\.php$>
Require all denied
</FilesMatch>
但是,你可以更具体一点,使用表达式包含完整的文件路径<If>
。例如:
<Files "*.php">
<If "%{REQUEST_URI} != '/subdir/folder/specific.php'">
Require all denied
</If>
</Files>
外部<Files>
容器不是必需的,因为您可以在<If>
表达式中执行所有操作。例如:
<If "%{REQUEST_URI} =~ /\.php$/ && %{REQUEST_URI} != '/subdir/folder/specific.php'">
Require all denied
</If>
或者,在单个表达式中使用负向前瞻(如前所述):
<If "%{REQUEST_URI} =~ m#^(?!/subdir/folder/specific\.php).+\.php$#">
Require all denied
</If>
或者,你可以使用 mod_rewrite:
RewriteEngine On
RewriteCond %{REQUEST_URI} !=/subdir/folder/specific.php
RewriteRule \.php$ - [F]
参考:
<Files>
-https://httpd.apache.org/docs/2.4/mod/core.html#files<FilesMatch>
-https://httpd.apache.org/docs/2.4/mod/core.html#filesmatch<If>
-https://httpd.apache.org/docs/2.4/mod/core.html#if- Apache 表达式 -https://httpd.apache.org/docs/2.4/expr.html
RewriteRule
(mod_rewrite)-https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewriterule