.htaccess中的条件-使用mod_rewrite测试env变量

m528fe3b  于 2023-10-23  发布在  其他
关注(0)|答案(1)|浏览(132)

当两个条件成立时我想否定。
我在apache2.conf中设置了一个变量:

SetEnv MY_SITE stage

然后在.htaccess中检查header和env变量是否匹配。

# check the variable is set by outputting to header. 
RewriteCond %{ENV:MY_SITE} (.+)
RewriteRule ^ - [E=MY_SITE:%1]
Header always set X-Site %{MY_SITE}e

然后拒绝访问,如果头是错误的,这是分段:

# check the azure header and that this is staging
RewriteCond %{HTTP:X-Azure-FDID} !^xxxxxx$ [NC]
RewriteCond %{ENV:MY_SITE} =stage
RewriteRule ^ - [F]

然而,第二条件不导致禁止消息。
如果我尝试这样做,它会工作并拒绝访问:

RewriteCond %{HTTP:X-Azure-FDID} !^xxxxxx$ [NC]
# RewriteCond %{ENV:MY_SITE} =stage
RewriteRule ^ - [F]

但这并不:

RewriteCond %{ENV:MY_SITE} =stage
RewriteRule ^ - [F]

为什么第二个条件不起作用?

ldioqlga

ldioqlga1#

SetEnv MY_SITE stage

SetEnv(mod_env)处理得太晚,mod_rewrite无法提取它(mod_rewrite处理得早)。您需要使用SetEnvIf(mod_setenvif)来设置env var,它处理得早得多。
SetEnv的文档所述:
此指令设置的内部环境变量是在大多数早期请求处理指令运行后设置的,例如访问控制和URI到文件名的Map。如果您要设置的环境变量是作为此早期处理阶段的输入(例如RewriteRule指令),则应该使用SetEnvIf设置环境变量。
SetEnvIf有一个不同的语法。要无条件地设置它,你需要做如下操作:

SetEnvIf ^ ^ MY_SITE=stage

第一个参数(^)是一个正则表达式,它匹配任何请求头。^总是成功的。
第二个参数(另一个^)是一个匹配前一个参数值的正则表达式。同样,这总是成功的。
.htaccess上下文中使用env vars和mod_rewrite时,需要小心重写引擎的任何循环。(例如,稍后在.htaccess文件中的标准前端控制器模式可能会触发此操作)。如果重写引擎在第二次通过时使用REDIRECT_前缀重命名第一次通过时设置的任何env变量(例如REDIRECT_MY_SITE)。第三遍,REDIRECT_REDIRECT_MY_SITE等。因此,您可能需要检查REDIRECT_<var>,或者防止重写引擎进行额外的传递。(servervirtualhost 上下文中的mod_rewrite指令默认情况下没有这种额外的复杂性。)

# check the variable is set by outputting to header. 
RewriteCond %{ENV:MY_SITE} (.+)
RewriteRule ^ - [E=MY_SITE:%1]
Header always set X-Site %{MY_SITE}e

鉴于上述情况,这并没有测试你认为它做了什么。在这种情况下,mod_rewrite规则什么也没有做(因为在处理这个规则时没有设置MY_SITE)。当Header被处理时(处理得很晚),SetEnv已经设置了env var。

使用Define替代

我已经在我的apache2.conf中设置了变量
然而,既然你可以访问服务器配置,那么考虑使用一个“defined”变量(使用Define指令)而不是一个环境变量。变量不能在.htaccessdefined(因为它们是在编译时设置的),但它们可以在.htaccess中测试,并且不会像env vars那样被“重命名”(如上所述)。
apache2.conf中:

Define MY_SITE stage

.htaccess中:

<IfDefine MY_SITE>
    RewriteCond %{HTTP:X-Azure-FDID} !^xxxxxx$ [NC]
    RewriteRule ^ - [F]
</IfDefine>

这显然不会检查MY_SITE的值,因此假设它只会在staging服务器上设置(实际上是一个布尔值)。因此,最好将变量名改为类似STAGING_SITE的名称。
如果MY_SITE可以包含多个值,那么您可以使用${<varname>}语法检查该值。例如:

<IfDefine MY_SITE>
    RewriteCond %{HTTP:X-Azure-FDID} !^xxxxxx$ [NC]
    RewriteCond ${MY_SITE} =stage
    RewriteRule ^ - [F]
</IfDefine>

相关问题