首页 > 解决方案 > 重写规则以防止 apache 在到达 htaccess 之前解码 url?

问题描述

我们有一个这样的 htaccess 规则:

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

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

我读过这个问题的解决方法是使用像%{REQUEST_URI} %{THE_REQUEST}htaccess 规则中的服务器变量,因为这些变量在使用前没有被解码,但很难实现。RewriteRule 中的问号让一切变得疯狂,我不知道如何逃脱它。

那里的任何专家可以帮助我修复以下规则以使其表现得像上面的规则吗?

RewriteCond %{REQUEST_URI} ^(.*)/(.*)/(.*)
RewriteRule . ../app%1/scripts/api/index.php?fn=%2&%3 [L]

标签: apache.htaccessmod-rewrite

解决方案


实际上,解决方案是使用名为THE_REQUEST.

来自mod_rewrite 文档

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]

请注意,您不应该使用相对路径进行内部重写,这可能会导致混淆。相反,定义 a RewriteBase,使用绝对路径或从域根目录开始使用 a /

更新

由于您可以在 url 中编码正斜杠,因此您需要设置AllowEncodedSlashesNoDecode(或On但它不安全)。还要注意,由于一个错误,您必须将此指令放在虚拟主机上下文中,即使服务器配置上下文被认为是好的(否则,它会被简单地忽略)。默认情况下,AllowEncodedSlashes设置为Off。因此,Apache 会自动处理编码的斜线并拒绝它们,而不会将请求传递给mod_rewrite. 请参阅此处的官方文档。


推荐阅读