Apache mod_重写%2B和加号(+;)

Apache mod_重写%2B和加号(+;),apache,mod-rewrite,Apache,Mod Rewrite,我正在使用apache/mod_rewrite重新编写URL,但我在加号方面遇到了问题 按照以下规则 RewriteRule ^/(.+[^/])/?$ http://localhost:8080/app/home?tag=$1 [P,L] 两者: 最终成为 uri=http://localhost:8080/app/home, args=tag=1+2 因此,在这两种情况下,应用程序都将加号转换为一个空格,这样就不能再区分空格和加号了 如果我使用“B”标志,那么在这两种情况下+符号都会转

我正在使用apache/mod_rewrite重新编写URL,但我在加号方面遇到了问题

按照以下规则

RewriteRule ^/(.+[^/])/?$ http://localhost:8080/app/home?tag=$1 [P,L] 
两者:

最终成为

uri=http://localhost:8080/app/home, args=tag=1+2
因此,在这两种情况下,应用程序都将加号转换为一个空格,这样就不能再区分空格和加号了

如果我使用“B”标志,那么在这两种情况下+符号都会转换为%2B,应用程序最终会出现相同的问题,但会出现相反的情况(空格和加号都是加号)

有没有办法让apache正确地将%2B转义为加号而不是空格

我读了一些关于mod_安全性的文章,但我没有使用它,所以我不确定是否有其他安全机制导致了这种情况


任何帮助都将不胜感激

不,这与参考问题不太一样。这里的问题是特别的加号,而答案并没有解决这个问题

斜杠也有一个问题,请参见 (但您确实需要访问Apache配置才能执行此操作-.htaccess不行)

事实上,单独使用重写规则是不可能的。Apache在重写URL之前对其进行解码,但它不理解加号:不会提供名为

“a b.html”

加号由PHP解码到查询字符串的$_GET数组(或任何相关的语言机制)中,因为浏览器中的表单处理程序将它们放在其中。因此,Apache将在应用重写之前将%2B转换为+,而不使用+本身,这意味着您无法区分两者之间的区别

当然,有人可能会争辩说,在这样的URL中,用作空格的+是无效的,应该只使用%20。但是,如果您无法控制生成它们,那么您肯定会看到它们。不过浏览器不会自动生成它们

答案是DIY,在许多方面它更容易预测和简化:

重写规则。*index.php[L]

因此,所有内容都将转换为index.php,并且不需要构造查询字符串。如果要排除某些模式,例如在中带有斜杠的模式,或存在显式文件的模式,则明显的修改适用。例如 重写cond%{REQUEST_FILENAME}-f

然后在index.php中

$uri=substr($\u SERVER['REQUEST\u uri'],1);//删除前导斜杠

$qmpos=strpos($uri,“?”);//是否有问号,如果有,在哪里

if($qmpos!==FALSE){$uri=substr($uri,0,$qmpos);}//仅限q.m之前的位

$decoded=urldecode($uri);//解码URL前面的部分

如果(!empty($decoded)){$\u GET['args']=$decoded;}//将结果添加到$\u GET

这将解码原始请求(不包括前导斜杠-如果您深入层次结构,可能会略有不同,但原理是相同的-并且不包括任何额外的查询字符串),并根据PHP的常规规则对args参数进行解码,并将其放入$\u GET中,这样您就可以按照通常的方式处理它和其余的$\u GET查询字符串参数

我认为这应该适用于空URL()或只有查询字符串()的URL,以及简单的case()和带有查询字符串的case()。毫无疑问,类似的方法也适用于其他语言


在您的特定情况下,您实际上根本不希望在PHP中解码这些加值。那很好,改用rawurldecode,它不会带来好处。

谢谢;这是我发现的唯一一篇正确回答URL本地部分+符号问题的帖子。上面答案中的关键短语是“事实上,单独使用重写规则是不可能的。Apache在重写URL之前对其进行解码,但它不理解加号”。
uri=http://localhost:8080/app/home, args=tag=1+2