在配置文件和 .htaccess 中的 Apache 指令中使用 RegEx

Using RegEx in Apache's directives in config files and .htaccess

如果我理解正确,下一段代码中的表达式 .ht* 将匹配所有以 .ht 开头的内容,所以我的 .ht_lalala 是安全的。

<Files ".ht*">
    Require all denied
</Files>

但是下一个呢?

(^\.ht|~$|back|BACK|backup|BACKUP$)

匹配文件是否正确:.htaccessbackbackupBACKUP?或者下一个会更好

(^\.ht*|back*|BACK*$)

我想了解的是 ~$ 在我的代码中(在 RegEx 模式中)的实际含义。我不知道为什么以及什么时候把它放在那里,但我的代码中有它,现在我怀疑它是否正确。


我了解 RegEx 的基本知识,什么是 ^$* 表示前面 text/token 中的 0 或 N,但是 ~ 在模式内部没有意义,除非它只是一个简单的字符并且它除了字面上匹配 ~ 什么都不做。我读过 Apache 文档,我想对于多个匹配 FilesMatch 和 DirectoryMatch 更好,但是正则表达式也可以用于指令:文件和目录,添加 ~ 字符,如文档示例中所述。

<Files ~ "\.(gif|jpe?g|png)$">
    #...
</Files>

好吧,我真正想要的是知道如何匹配不同的文件或目录。

还有一件事,我应该转义 . 吗?因为默认 httpd.conf 不这样做。或者它只是 httpd.conf 和 .htaccess 的不同(这对我来说没有意义)


更新

回答我自己的问题,首先我如何与 RegEx 匹配 .ht、.htaccess、.htpasswd、back、BACK、backup、BACKUP我决定在我想隐藏的任何东西的名称中使用 .(点)。其次,我发现简洁的模式 ^(\..*)$ 会完成这项工作,会给我我需要的东西。或 ^\. 因此,如果以后我想隐藏某些内容,我只需在名称的开头添加 .

我们开始吧,下一段代码将拒绝从网络访问名称以 . 开头的任何文件和目录(已测试,有效)

RegEx 模式匹配:

<FilesMatch "^\.">
    Require all denied
</FilesMatch>

<DirectoryMatch "^\.">
    Require all denied
</DirectoryMatch>

并且在精彩的解释中 我的方法,所以我坚持这个(经过测试,有效)

通配符字符串匹配:

<Files ".*">
    Require all denied
</Files>

<Directory ".*">
    Require all denied
</Directory>

Apache manual 涵盖了这一点。

~ 启用正则表达式。没有它,您只能访问通配符 ?*.

据我所知,Apache 使用正则表达式的 PCRE 风格。

因此,一旦您通过 ~ 启用了正则表达式,然后使用 https://regex101.com/r/lPkMHK/1 来测试您编写的正则表达式的行为。

<Files ".ht*">

在此上下文中,.ht* 不是 正则表达式 (regex)。它是一个“wild-card 字符串”,其中 ? 匹配任何单个字符,* 匹配任何字符序列。 (虽然这也是一个有效的正则表达式 - 正则表达式会以不同的方式匹配)。

But what about next one?

(^\.ht|~$|back|BACK|backup|BACKUP$)

这是一个正则表达式(它不能在 <Files> 指令中使用,正如您在上面所写的那样,如果没有启用与 ~ 参数匹配的正则表达式模式 - 正如您稍后使用的那样。)

在此正则表达式中,~$ 匹配任何以文字 ~(波浪字符)结尾的字符串。这有时用于标记 backup 个文件。

它也匹配...

  • 任何以 .ht 开头的字符串(自然包括 .htaccess)。
  • 任何包含backBACKbackup的字符串(匹配backup显然是多余的)。
  • 任何以 BACKUP 结尾的字符串。

因此,这看起来并不像您认为的那样。

Or next will be better instead

(^\.ht*|back*|BACK*$)

虽然这是一个有效的正则表达式,但您显然已经恢复到“wild-card”模式匹配的混合。请记住,在正则表达式中,* 量词匹配 previous 标记 0 次或更多次。它不匹配“任何字符”,如 wild-card 模式匹配。

这仍然匹配“.htaccess”,但这只是因为模式没有锚定。例如,^\.ht*$(带有 end-of-string 锚点)将 匹配“.htaccess”。

<Files ~ "\.(gif|jpe?g|png)$">

使用 Files 指令,~ 参数启用正则表达式模式匹配。 (正如您所说。)这与在正则表达式模式本身内部使用 ~ 时完全不同。

One more thing, should I escape the .? Because default httpd.conf doesn't do so. Or it's just different for httpd.conf and .htaccess (which doesn't make sense to me)

我认为你把事情搞混了。在您的第一个示例中,它不是正则表达式,而是“wild-card”模式(如上所述)。在这种情况下,. 不能是 backslash-escaped。它匹配文字 .(点)。 . 在这里没有特殊含义。只有在需要匹配 正则表达式 .

中的文字点时,才应转义 .

例如,以下是等价的:

# Wild-card string match
<Files ".ht*">

# Regex pattern match
<Files ~ "^\.ht">

(但是,最好使用 FilesMatch 而不是 Files ~ 以避免混淆。FilesMatch 是“较新”的语法。)

httpd.conf.htaccess在这方面没有区别。


更新:

I found out that laconic pattern ^(\..*)$ will do the job ...

Here we go, next code will deny access from the web to any files and directories which names start with . (tested, works)

<FilesMatch "^(\..*)$">
    Require all denied
</FilesMatch>

这可以简化。您不需要完全匹配整个文件名。您只需要断言文件名以点开头(这样效率更高)。因此,您不需要 捕获 (带括号的子模式)文件名 - 您没有对它做任何事情。

要使用正则表达式断言文件名以点开头,则只需使用 ^\. - 仅此而已。例如:

<FilesMatch "^\.">

请记住,正则表达式量词(例如 *)默认为 greedy,因此您无需遵循 .* 这样的模式匹配文件名时带有 end-of-string 锚点。因此,正则表达式 ^.*$.* 在这种情况下实际上是相同的。两者都匹配整个文件名。 (在此上下文中没有换行符。)

这可以进一步“简化”,方法是根本不使用正则表达式,而是使用带有原始 <Files> 指令的 wild-card 字符串模式。例如,这等同于:

<Files ".*">

注意:这不是正则表达式。它是一个文字点,后跟任意数量的字符(wild-card 语法)。