如果我理解正确,下一个代码中的表达式 .ht*
将匹配以 .ht 开头的所有内容,所以我的 .ht_lalala
是安全的。
<Files ".ht*">
Require all denied
</Files>
但是下一个呢?
(^\.ht|~$|back|BACK|backup|BACKUP$)
匹配文件是否正确:.htaccess
、back
、backup
、BACKUP
?否则接下来会更好
(^\.ht*|back*|BACK*$)
我想了解的是 ~$
在我的代码中的实际含义(在 RegEx 模式中)。我不知道为什么以及何时将它放在那里,但我的代码中有它,现在我怀疑它是否正确。
我知道关于 RegEx 的基本知识,什么是 ^
和 $
,并且 *
表示先前文本/标记中的 0 或 N,但 ~
在模式中没有意义,除非它只是一个简单的字符,除了字面上匹配 ~
之外什么都不做。我已经阅读了 Apache 文档,我猜想多个匹配 FilesMatch 和 DirectoryMatch 更好,但是正则表达式也可以用于指令:文件和目录,加上 ~ 字符,如文档示例中所述。
<Files ~ "\.(gif|jpe?g|png)$">
#...
</Files>
好吧,我真正想要的是知道如何匹配不同的文件或目录。
还有一件事,我应该逃避 .
吗?因为默认 httpd.conf 不这样做。或者它只是 httpd.conf 和 .htaccess 不同(这对我来说没有意义)
更新
回答我自己的问题,我如何与 RegEx 中的任何一个匹配 .ht、.htaccess、.htpasswd、back、BACK、backup、BACKUP,首先我决定在名称中使用 .
(点)任何我想隐藏的东西。其次,我发现简洁的模式 ^(\..*)$
可以完成这项工作,会给我我需要的东西。或者 ^\.
https://stackoverflow.com/a/72291982/10324990 所以,如果将来我想隐藏一些东西,我只需在名称的开头添加 .
即可。
我们开始吧,下一个代码将拒绝从网络访问任何名称以 .
开头的文件和目录(已测试,有效)
RegEx 模式匹配:
<FilesMatch "^\.">
Require all denied
</FilesMatch>
<DirectoryMatch "^\.">
Require all denied
</DirectoryMatch>
在精彩的解释中https://stackoverflow.com/a/72291982/10324990我的方法,所以我坚持这个(经过测试,有效)
通配符字符串匹配:
<Files ".*">
Require all denied
</Files>
<Directory ".*">
Require all denied
</Directory>
回答1
<Files ".ht*">
在这种情况下,.ht*
不是正则表达式 (regex)。它是一个“通配符字符串”,其中 ?
匹配任何单个字符,而 *
匹配任何字符序列。 (虽然这也是一个有效的 regex - regex 会以不同的方式匹配)。
但是下一个呢?
(^\.ht|~$|back|BACK|backup|BACKUP$)
这是一个 regex (它不能像你上面写的那样在 <Files>
指令中使用,没有启用与 ~
参数匹配的 regex 模式 - 正如你稍后使用的那样。)
在这个 regex 中,~$
匹配任何以文字 ~
(波浪字符)结尾的字符串。这有时用于标记备份文件。
它也符合...
- 任何以
.ht
开头的字符串(自然包括.htaccess
)。 - 任何包含
back
或BACK
或backup
的字符串(匹配backup
显然是多余的)。 - 任何以
BACKUP
结尾的字符串。
因此,这看起来不像你认为它正在做的那样。
否则接下来会更好
(^\.ht*|back*|BACK*$)
虽然这是一个有效的 regex,但您显然已恢复为“通配符”模式匹配的混合。请记住,在 regex 中,*
量词匹配前一个标记 0 次或更多次。它不匹配“任何字符”,如通配符模式匹配。
这仍然匹配“.htaccess”,但只是因为模式没有锚定。例如,^\.ht*$
(带有字符串结尾锚)将不匹配“.htaccess”。
<Files ~ "\.(gif|jpe?g|png)$">
使用 Files
指令,~
参数启用 regex 模式匹配。 (正如您所说。)这与在 regex 模式本身中使用 ~
时完全不同。
还有一件事,我应该逃避
.
吗?因为默认 httpd.conf 不这样做。或者只是 httpd.conf 和 .htaccess 不同(这对我来说没有意义)
我觉得你把事情搞混了。在您的第一个示例中,它不是 regex,而是“通配符”模式(如上所述)。在这种情况下,.
不得进行反斜杠转义。它匹配文字 .
(点)。 .
在这里没有特殊含义。只有当您需要匹配正则表达式中的文字点时,才应转义 .
。
例如,以下是等价的:
# Wild-card string match
<Files ".ht*">
和
# Regex pattern match
<Files ~ "^\.ht">
(但是,最好使用 FilesMatch
而不是 Files ~
以避免任何混淆。FilesMatch
是“较新”的语法。)
httpd.conf
和 .htaccess
在这方面没有区别。
更新:
我发现简洁的模式
^(\..*)$
可以完成这项工作......我们开始吧,接下来的代码将拒绝从网络访问任何名称以
.
开头的文件和目录(经过测试,有效)<FilesMatch "^(\..*)$"> Require all denied </FilesMatch>
这可以简化。您不需要逐字匹配整个文件名。您只需要断言文件名以点开头(这样效率更高)。因此,您不需要捕获(带括号的子模式)文件名 - 您没有对它做任何事情。
要使用 regex 断言文件名以点开头,然后只需使用 ^\.
- 仅此而已。例如:
<FilesMatch "^\.">
请记住,默认情况下 regex 量词(例如 *
)是贪婪的,因此在匹配文件名时,您不需要遵循像 .*
这样的带有字符串结尾锚点的模式。因此, regex ^.*$
和 .*
在这种情况下实际上是相同的。两者都匹配整个文件名。 (在此上下文中没有换行符。)
这可以通过完全不使用 regex 并使用带有普通 <Files>
指令的通配符字符串模式来进一步“简化”。例如,这与以下内容相同:
<Files ".*">
注意:这不是 regex。它是一个文字点,后跟任意数量的字符(通配符语法)。
回答2
https://httpd.apache.org/docs/2.4/mod/core.html#files 涵盖了这一点。
~
启用 regex。没有它,您只能访问通配符 ?
和 *
。
据我所知Apache 使用regex 的PCRE 风格。
因此,一旦您通过 ~
启用了 regex,然后使用 https://regex101.com/r/lPkMHK/1 来测试您编写的 regex 的行为。