Apache mod_rewrite %2B 和加号 (+)

发布于 2024-08-26 15:42:40 字数 587 浏览 5 评论 0原文

我正在使用 apache / mod_rewrite 来重写 URL,但我遇到了加号问题。

使用以下规则..

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

两者:

http://localhost/1+1 and http://localhost/1%2B2

最终都是

uri=http://localhost:8080/app/home, args=tag=1+2

因此,在这两种情况下,应用程序都会将加号转换为空格,因此它无法再区分空格和加号。

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

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

我读过一些有关 mod_security 的内容,但我没有使用它,所以我不确定是否有其他安全机制导致了这种情况?

任何帮助将不胜感激!

I'm using apache / mod_rewrite to re-write URLs but I am having problems with the plus sign.

With the following rule..

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

Both:

http://localhost/1+1 and http://localhost/1%2B2

end up as

uri=http://localhost:8080/app/home, args=tag=1+2

So in both cases the application translates the plus sign into a space so it cannot differentiate between spaces and plus signs anymore.

If I use the "B" flag, then in both cases the + signs are translated into %2B and the application ends up with the same problem but reversed (both spaces and plus signs are plus signs)

Is there a way to get apache to properly escape %2B into a plus sign and not a space?

I read something about mod_security but I am not using that so I am not sure if there is some other security mechanism that is causing this?

Any help would be greatly appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

守不住的情 2024-09-02 15:42:40

不,这与引用的问题不太一样。这里的问题特别是加号和 Apache 的答案: mod_rewrite: 空间 & URL 中的特殊字符不起作用 并不能解决这个问题。

斜杠也存在问题,请参阅 http://httpd。 apache.org/docs/current/mod/core.html#allowencodedslashes
(但您确实需要访问 Apache 配置才能执行此操作 - .htaccess 不会这样做)。

事实上,单独使用重写规则不可能。 Apache 在重写之前对 URL 进行解码,但是它不理解加号:http://example.com/a+b.html 不会提供名为

“a b.html”。

加号由 PHP 解码为查询字符串的 $_GET 数组(或任何相关的语言机制),因为浏览器中的表单处理程序将它们放入其中。因此 Apache 会在应用重写之前将 %2B 转换为 +,并保留 +单独来看,这意味着您无法区分。

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

答案是 DIY,在很多方面它更可预测、更简单:

RewriteRule .* index.php [L]

因此,所有内容都会变成index.php,并且不会尝试构造查询字符串。如果您想排除某些模式,例如带有斜杠的模式,或者确实存在显式文件的模式,则适用明显的修改。例如
RewriteCond %{REQUEST_FILENAME} !-f

然后在index.php中

$uri = substr($_SERVER['REQUEST_URI'], 1); // 删除前导斜杠

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

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

$已解码= urldecode($uri); // 解码 URL 之前的部分

if (!empty($decoded)) { $_GET['args'] = $decoded; } // 将结果添加到$_GET

解码原始请求(不包括前导斜杠 - 如果您处于层次结构的更深处,情况会略有不同,但原理是相同的 - 并且排除任何额外的查询字符串),并根据 PHP 的正常规则解码 args 参数并将其放入 $_GET 中,以便您可以以通常的方式将其与其余 $_GET 查询字符串参数一起处理。

我相信这应该适用于空网址(http://example.com/)或只有查询的网址字符串 (http://example.com/?foo=1),以及简单的case (http://example.com/bar) 以及带有查询字符串的 case (http://example.com/bar?foo=1)。毫无疑问,类似的方法也适用于其他语言。

在您的特定情况下,您实际上根本不希望在 PHP 中解码加号。没关系,使用 rawurldecode 代替,这没有好处。

No, this isn't quite the same as the referenced question. The problem here is specifically plus signs and the answer to Apache: mod_rewrite: Spcaes & Special Characters in URL not working doesn't address that.

There's also an issue with slashes, for which see http://httpd.apache.org/docs/current/mod/core.html#allowencodedslashes
(but you do need access to the Apache config to do this - .htaccess won't do).

In fact it is impossible to do using a rewrite rule alone. Apache decodes the URL before putting it through rewrite, but it doesn't understand plus signs: http://example.com/a+b.html wouldn't deliver a file called

"a b.html".

The plus signs are decoded by PHP into the $_GET array (or whatever the relevant language mechanism is) for query strings, because form handlers in browsers put them in. So Apache will translate %2B to + before applying the rewrite, and leave + itself alone, meaning you can't tell the difference.

Of course, one could argue that + used as space is simply invalid in such URLs and one should use only %20. However, if you don't have control over generating them, you're bound to see them. Browsers won't generate them automatically though.

The answer is DIY, and in many ways it is more predictable and simpler:

RewriteRule .* index.php [L]

Hence everything turns into index.php and there's no attempt to construct a query string. If you want to exclude certain patterns, e.g. those with slashes in, or where an explicit file does exist, the obvious amendments apply. e.g.
RewriteCond %{REQUEST_FILENAME} !-f

Then in index.php

$uri = substr($_SERVER['REQUEST_URI'], 1); // remove leading slash

$qmpos = strpos($uri, '?'); // is there a question mark, if so where

if ($qmpos !== FALSE) { $uri = substr($uri, 0, $qmpos); } // only the bit before q.m.

$decoded = urldecode($uri); // decode the part before the URL

if (! empty($decoded)) { $_GET['args'] = $decoded; } // add result to $_GET

That decodes the original request (excluding the leading slash - would be slightly different if you're deeper down a hierarchy, but the principle is the same - and excluding any additional query string), and decodes the args parameter according to PHP's normal rules and puts it into $_GET so you can process it along with the rest of the $_GET query string parameters in the usual way.

I believe this should work for empty URLs (http://example.com/) or those which only have a query string (http://example.com/?foo=1), as well as the simple case (http://example.com/bar) and the case with a query string as well (http://example.com/bar?foo=1). No doubt similar approaches will work for other languages.

In your particular case, you actually don't want the pluses decoded in the PHP at all. That's fine, use rawurldecode instead, which doesn't do pluses.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文