.htaccess:如何为缺少结尾斜杠的目录返回404而不是301

ao218c7q  于 2023-05-07  发布在  其他
关注(0)|答案(1)|浏览(135)

我想通过返回404状态来隐藏我现有的文件和目录,这些文件和目录不适合访问者。到目前为止,我已经成功地涵盖了这些场景(假设我有一个文件“file.txt”和一个名为“dir”的目录):

  • example.net/file.txt 返回404 ✔
  • example.net/dir/ 返回404 ✔
  • example.net/dir/anyFileIHaveHere.txt 返回404 ✔

但是,“example.net/dir返回301状态,位置为“example.net/dir/”。我读到浏览器会记住301重定向,所以为了确保没有缓存干扰我的测试,我通过curl发送请求:curl -H 'Cache-Control: no-cache, no-store' -X GET -v 'https://example.net/dir'
它只发生在现有的目录中,所以这个方法可以用来“猜测”我想要阻止的目录。为了返回404,我已经尝试了所有我在网上找到的东西,但到目前为止都没有一个工作:

  • Error Document 301/pages/404.php
  • RewriteRule“/dir”“/pages/404.php”
  • 目录删除
  • 文件将dir与deny from all匹配
  • 位置目录,拒绝来自所有

也许我只是没有正确地使用或组合它们,或者可能有其他的东西。如果这是一个信号的话,主人就是hostinger。我需要的方法是什么?
我当前的.htaccess在root中:

ErrorDocument 403 /pages/404.php
ErrorDocument 404 /pages/404.php

<FilesMatch "file1|file2|fileN">
  order Allow, Deny
  deny from all
</FilesMatch>

.htaccess in /dir:

Deny from all
knsnq2tg

knsnq2tg1#

您需要在根.htaccess文件中使用DirectorySlash Off(如您所建议的),以防止mod_dir通过301(永久)重定向在文件系统目录上追加尾部斜杠。
但是,这本身不会触发/dir/.htaccess文件(“阻止”请求),因为这需要目录上的尾部斜杠。您可以手动使用mod_rewrite在尾部添加斜杠,或者直接使用mod_rewrite来“阻止”请求(更可取)。所谓“阻止”,我的意思是提供一个404 -不需要触发一个403并在PHP自定义错误文档中覆盖它。
您可能还需要设置RewriteOptions AllowNoSlash以允许mod_rewrite匹配不以斜杠结尾的目录。(我说“可能”,因为这并不总是必要的,尽管文档建议它是。)
请注意,DirectorySlash Off将防止将尾随的斜杠附加到任何目录。因此,根据您的场景,如果您有其他需要访问的目录,您可能需要根据需要手动附加尾部斜杠。
另外请注意(如您所指出的),301重定向是由浏览器永久缓存的。毕竟,它们是“永久性的”。(您可以通过发送适当的Cache-ControlExpires标头来控制缓存。)
因此,在根.htaccess中,您可以添加以下内容:

# Root ".htaccess"

# Directory listings "must" be disabled when "DirectorySlash Off" is set
Options -Indexes

# Prevent mod_dir appending the trailing slash with a 301 redirect
DirectorySlash Off

RewriteEngine On

# Allow mod_rewrite to match directories that do not end with a slash
RewriteOptions AllowNoSlash

# Trigger 404 when directory (or any file in that directory) is requested
# Directory can be requested with or without the trailing slash
RewriteRule ^dir(/|$) - [R=404]

请注意,RewriteRule * 模式 * 匹配的URL路径不是以斜杠开头。
不再需要/dir子目录中的.htaccess文件。
您可以对需要阻止的所有文件和目录使用相同的方法。不需要覆盖/设置“404 Not Found”响应的403 ErrorDocument。例如,完整的文件如下所示:

ErrorDocument 404 /pages/404.php

Options -Indexes

DirectorySlash Off

RewriteEngine On

RewriteOptions AllowNoSlash

# Trigger 404 for specific files and directories (and all files in those directories)
RewriteCond %{REQUEST_URI} ^/dir(/|$) [OR]
RewriteCond %{REQUEST_URI} ^/another-dir(/|$) [OR]
RewriteCond %{REQUEST_URI} ^/file1\.txt$ [OR]
RewriteCond %{REQUEST_URI} ^/file2\.txt$
RewriteRule . - [R=404]

请注意,REQUEST_URI服务器变量包含完整的根相对(以斜杠开头)URL路径。与RewriteRule * 模式 * 不同,它是相对于包含.htaccess文件的目录的,因此 * 不 * 以斜杠开头。

<FilesMatch "file1|file2|fileN">

请注意,这匹配任何文件(文件系统上的任何位置),其中 * 包含 * 文件名(而不是文件路径)中的任何位置的file1file2fileN。因此,文件/foo/bar/abcfile1xyz.txt将通过此规则成功匹配。如果你愿意,你可以在mod_rewrite条件或规则中重复这个过程。例如:

RewriteCond %{REQUEST_URI} file1|file2|fileN [OR]

附加说明…

ErrorDocument 301 /pages/404.php

这可能允许您覆盖重定向响应的HTTP响应 body(通常被用户代理忽略),但您不能使用此方法覆盖3xx重定向。3xx响应由HTTP状态和Location报头组成。

RewriteRule "/dir" "/pages/404.php"

如上所述,RewriteRulepattern 匹配的URL路径不是以斜杠开头的。所以这绝对不吻合。(但是,您应该直接触发404,而不是内部重写到404错误文档。然后Apache设置正确的状态码,而不依赖于PHP。
文件将dir与deny from all匹配
FilesMatch指令只匹配物理文件,而不匹配目录。
位置目录,拒绝来自所有
.htaccess上下文中不允许使用Location指令,因此这应该导致Apache上的500内部服务器错误。(在LiteSpeed上,它可能会被忽略。

order Allow, Deny
deny from all

这些是Apache 2.2指令,以前在Apache 2.4中已被弃用(我假设您使用的是Apache 2.4)。这里应该使用Require all denied。但是,您不应该在同一上下文中混合使用来自两个模块的auth指令,因为这可能会导致意外的冲突。

相关问题