重写规则以防止apache在到达htaccess之前解码url?

时间:2018-10-19 09:34:39

标签: apache .htaccess mod-rewrite

我们有这样的htaccess规则:

RewriteRule ^(.*)/(.*)/(.*) ../app$1/scripts/api/index.php?fn=$2&$3 [L]

这在大多数情况下都可以正常工作,但是,Apache在到达该规则之前会对URL进行解码,因此htaccess将类似beta/list/&cat=red%20%26%20blue的URL视为beta/list/&cat=red & blue,因此我们得到了{{1} }和cat='red'进入blue=null而不是index.php

我已经读到,解决此问题的方法是在htaccess规则中使用服务器变量,例如cat='red & blue' %{REQUEST_URI},因为这些变量在使用前不会被解码,但是很难实现。 RewriteRule中的问号使一切变得疯狂,我不知道如何逃避它。

那里的任何专家都可以帮助我修正下面的规则,使其表现出与上面相同的方式吗?

%{THE_REQUEST}

1 个答案:

答案 0 :(得分:1)

实际上,解决方案是使用名为THE_REQUEST的特殊服务器变量。

来自mod_rewrite documentation

  

THE_REQUEST

     

浏览器发送到服务器的完整HTTP请求行(例如,   “ GET /index.html HTTP / 1.1”)。这不包括任何其他   浏览器发送的标头。 此值尚未释放   (已解码),与下面的大多数其他变量不同。

这是您的规则的外观

# don't touch urls ending by index.php
RewriteRule index\.php$ - [L]

# user request matching /xxx/xxx/xxx (with optional query string)
RewriteCond %{THE_REQUEST} \s/([^/\?]+)/([^/\?]+)/([^\?]+)(?:\s|\?) [NC]
RewriteRule ^ ../app%1/scripts/api/index.php?fn=%2&%3 [L,QSA]

请注意,您不应该使用相对路径进行内部重写,否则可能导致混乱。而是定义一个RewriteBase,使用绝对路径或从域根开始以/开始。

更新

由于您可以在网址中编码正斜杠,因此需要将AllowEncodedSlashes设置为NoDecode(或On,但这是不安全的)。另请注意,由于存在错误,即使据说 server config 上下文还可以,您也必须将此指令放入虚拟主机上下文中(否则,简单地忽略)。默认情况下,AllowEncodedSlashes设置为Off。因此,Apache会自动自行处理编码的斜杠并拒绝它们,而不会将请求传递给mod_rewrite。请参阅官方文档here