如何访问由表达式中的重写规则设置的环境变量?

Chr*_*ris 0 rewrite .htaccess http-basic-authentication apache-2.4

我正在开发具有公共和私有部分的 Symfony 3.4 应用程序。但是,我目前正在为此应用程序设置一个只能由授权用户访问的临时系统,因此我在整个应用程序前面放置了一个 .htaccess 基本身份验证。

应用程序中有一条路由需要由不提供身份验证的外部应用程序访问。我只想为这条单一路由禁用 .htaccess 身份验证。此路由的所有 URL 都采用/api/post-result/123where123是任意 ID的形式。

在四处搜索之后,我试图通过Require expr我的 .htaccess 中的一个条目来解决这个问题,该条目将简单地匹配 URL。但是,由于 Symfony 进行 URL 重写,REQUEST_URI在服务器(以及我的情况)中始终显示为“app.php”。我尝试了其他变量,例如QUERY_STRINGor PATH_INFO,但它们似乎都没有包含我的实际请求 URI。然后我尝试使用重写规则将匹配的 URI 放入环境变量中。但是,这似乎无法通过表达式读取。

这是我的 .htaccess 文件

DirectoryIndex app.php

<IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
    RewriteRule ^(.*) - [E=BASE:%1]

    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]

    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule .? - [L]

    RewriteRule ^(.*)$ %{ENV:BASE}/app.php [L,E=SFURI:$1] # <-- env variable is set here
</IfModule>

<IfModule !mod_rewrite.c>
    <IfModule mod_alias.c>
        RedirectMatch 302 ^/$ /app.php/
    </IfModule>
</IfModule>

<Files "*.php">
  AuthUserFile /srv/my/app/.htuser
  AuthName "Authentication Required"
  AuthType Basic

  # allow access to post-result api without authentication
  # THIS DOES NOT WORK as reqenv('SFURI') is always empty
  Require expr "reqenv('SFURI') =~ m#/api/post-result/.*$#"
  # require authentication for everything else
  Require valid-user
</Files>
Run Code Online (Sandbox Code Playgroud)

查看Apache日志,环境变量设置正确:

[rewrite:trace5] [pid 11010] mod_rewrite.c(476): [...] 将环境变量“SFURI”设置为“api/post-result/123”

[rewrite:trace1] [pid 12755] mod_rewrite.c(476): [...] 使用 /app.php 进行内部重定向 [内部重定向]

但是,由于某种原因,当我稍后尝试访问它时,该变量为空。是否有可能在由上次重写规则引起的内部重定向中清除所有环境变量?日志显示条件不匹配,当我更改条件以检查变量是否为空时,条件返回为真。我也尝试过使用env函数而不是reqenv,但行为是相同的。

[authz_core:trace4] [pid 11010] util_expr_eval.c(860): [...] 来自 /srv/my/app/.htaccess:36 的表达式评估给出:0

[authz_core:debug] [pid 11010] mod_authz_core.c(809): [...] AH01626: Require expr "reqenv('SFURI') =~ m#/api/post-result/.*$# 的授权结果”:拒绝

我该怎么做才能让我的表达式找到重写规则设置的环境变量?

Chr*_*ris 5

事实证明,由最后一个重写规则引起的内部重定向在所有变量前加上REDIRECT_. 为了访问表达式中的变量,它需要被访问为REDIRECT_SFURI

StackOverflow 上也讨论了这个问题:在 Apache RewriteRule 指令中设置环境变量时,是什么导致变量名称以“REDIRECT_”为前缀?