但

我有一个虚拟主机,它的一些访问限制配置如下:

<Location "/">
    AuthType Basic
    AuthName "Restricted Content"
    AuthUserFile /var/www/domain/htdocs/.htpasswd
    Require valid-user
</Location>

除此之外,我还有以下conf文件:

Alias /.well-known/acme-challenge/ "/var/www/letsencrypt/"

<Location /.well-known/acme-challenge/>
    # Security Options
    Options None
    AllowOverride None
    ForceType text/plain
    RedirectMatch 404 "^(?!/\.well-known/acme-challenge/[\w-]{43}$)"

    # Do not redirect to https or perform other rewrites
    RewriteEngine off

</Location>

我需要/.well-known/acme-challenge/无需授权即可访问。

我已经尝试Require all granted向我的conf文件中添加不同的变体,但无济于事。

如何才能使/.well-known/acme-challenge/所有虚拟主机无需身份验证即可访问?(我不想修改任何虚拟主机,这个虚拟主机只是一个例子)。

答案1

无法<Location />在服务器上下文中覆盖虚拟主机上下文中的语句。从阿帕奇文档

节内的节<VirtualHost>在虚拟主机定义之外的相应节之后应用。这允许虚拟主机覆盖主服务器配置。

合并的顺序是(最后合并的组获胜):

  1. <Directory>(正则表达式除外)和 .htaccess 同时完成(如果允许,则使用 .htaccess 覆盖<Directory>
  2. <DirectoryMatch>(和<Directory "~">
  3. <Files><FilesMatch>同时完成
  4. <Location><LocationMatch>同时完成
  5. <If>

除此之外<Directory>,每个组都按照它们在配置文件中出现的顺序进行处理。

<VirtualHost>不允许进入,<If>所以<Location>最后合并。

如果您仅在 https vhost 中为网站提供服务(由于身份验证,这是合理的),您可以执行以下操作(不会影响您的 https vhost):

Apache v2.2

<VirtualHost *:80>
  ServerName example.com
  Include letsencrypt-well-known.conf
  RedirectMatch permanent ^(?!/\.well-known/acme-challenge/)(.*) "https://example.com$1"
</VirtualHost>

<VirtualHost *:443>
  ServerName example.com
  DocumentRoot /var/www/html
  <Location "/">
    AuthType Basic
    AuthName "Restricted Content"
    AuthUserFile /var/www/domain/htdocs/.htpasswd
    Require valid-user
  </Location>
  ...
</VirtualHost>

letsencrypt-well-known.conf

<IfModule mod_proxy.c>
  ProxyPass /.well-known !
</IfModule>

Alias /.well-known/ /var/www/html/.well-known/

<Location /.well-known/acme-challenge>
  Options None
  Require all granted
</Location>

Apache v2.4

<Macro RedirectTo $protocol $domain>
  <If "'${well_known_enabled}' == 'On' && %{REQUEST_URI} =~ m#^/\.well-known(/|$)#">
    # Do nothing
  </If>
  <ElseIf "tolower(req('Host')) != '$domain' || tolower(%{REQUEST_SCHEME}) != '$protocol'">
    Redirect permanent / $protocol://$domain/
  </ElseIf>
</Macro>

<VirtualHost *:80>
  ServerName example.com
  Include letsencrypt-well-known.conf
  RedirectTo https example.com
</VirtualHost>

<VirtualHost *:443>
  ServerName example.com
  DocumentRoot /var/www/html
  <Location "/">
    AuthType Basic
    AuthName "Restricted Content"
    AuthUserFile /var/www/domain/htdocs/.htpasswd
    Require valid-user
  </Location>
  ...
</VirtualHost>

letsencrypt-well-known.conf

<IfModule mod_proxy.c>
  ProxyPass /.well-known !
</IfModule>

Define well_known_enabled On
Define well_known_root "/var/www/html"

Alias /.well-known/ "${well_known_root}/.well-known/

<Directory "${well_known_root}/.well-known">
  Options None
  AllowOverride None
  Require all granted
</Directory>

<Location /.well-known/acme-challenge>
  Options None
  Require all granted
</Location>

答案2

在 Apache 2.4 中,您可以Require expr向第一个位置块添加一个语句并评估请求 URI,如下所示:

Require expr %{REQUEST_URI} =~ m#^/.well-known/acme-challenge/.*#

或类似的东西(语法实际上没有测试过)。奇怪的m#语法是正则表达式可以/在字符串中使用的另一种形式。

expr文档:https://httpd.apache.org/docs/2.4/expr.html

相关内容