【问题标题】:htaccess redirect based on query parameter valuehtaccess 基于查询参数值的重定向
【发布时间】:2018-01-22 13:17:28
【问题描述】:

我的应用程序曾经使用lang.php 文件进行语言切换。 /path/to/page.php?foo=bar 重定向到英语的 URL 如下所示:

/path/to/lang.php?lang=en-CA&uri=%2Fpath%2Fto%2Fpage.php%3Ffoo%3Dbar

最近进行了一些更改,以在所有页面上接受 lang 查询参数。所以这个网址更好:

/path/to/page.php?foo=bar&lang=en-CA

我希望能够将 .htaccess 文件添加到我拥有 lang.php 文件的所有位置,以便在没有 lang.php 文件的情况下保持现有 URL 正常工作。这可能吗?

RewriteRules 必须与 lang.php 完全相关,因为应用程序在不同的主机名和路径上运行。

我根据the answer here 尝试了一下,但这给了我一个 404:

RewriteCond %{REQUEST_FILENAME} lang.php$
RewriteCond %{QUERY_STRING} (?:^|&)uri=([^&]+) [NC]
RewriteRule lang.php - [E=LANG_REDIR_URI:%1]

RewriteCond %{REQUEST_FILENAME} lang.php$
RewriteCond %{QUERY_STRING} (?:^|&)lang=([^&]+) [NC]
RewriteRule lang.php - [E=LANG_REDIR_LANG:%1]

RewriteCond %{REQUEST_FILENAME} lang.php$
RewriteRule . %{LANG_REDIR_URI}e [L,R=temporary]

uri 参数可能已经有查询参数(如上例所示),并且代码不应使应用程序容易受到open redirect vulnerability 的攻击。

不同的情况:

  • 带有查询字符串的URI,语言优先:/foo/bar/lang.php?lang=en-CA&uri=%2Ffoo%2Fbar%2Fpage.php%3Fid%3D123 应该重定向到/foo/bar/page.php?id=123&lang=en-CA
  • URI 没有查询字符串,语言优先:/foo/bar/lang.php?lang=en-CA&uri=%2Ffoo%2Fbar%2Fpage.php 应该重定向到/foo/bar/page.php?lang=en-CA
  • 带有查询字符串的URI,uri首先:/foo/bar/lang.php?uri=%2Ffoo%2Fbar%2Fpage.php%3Fid%3D123&lang=en-CA应该重定向到/foo/bar/page.php?id=123&lang=en-CA
  • URI 没有查询字符串,uri 首先:/foo/bar/lang.php?uri=%2Ffoo%2Fbar%2Fpage.php&lang=en-CA 应该重定向到/foo/bar/page.php?lang=en-CA

重定向中查询参数的顺序无关目标

更新

https://stackoverflow.com/a/45732670/404623 提供初步答案后,我尝试了以下 .htaccess 规则:

# This only works for uri values without query strings

RewriteCond %{QUERY_STRING} ^(lang=[^&]+)&uri=([^&]+) [NC]
RewriteRule lang\.php$ /%2\?%1 [L,NE,R=temporary]
RewriteCond %{QUERY_STRING} ^uri=([^&]+)&(lang=[^&]+) [NC]
RewriteRule lang\.php$ /%1\?%2 [L,NE,R=temporary]

# This only works for uri values with query strings

RewriteCond %{QUERY_STRING} ^(lang=[^&]+)&uri=([^&]+) [NC]
RewriteRule lang\.php$ /%2&%1? [L,NE,R=temporary]
RewriteCond %{QUERY_STRING} ^uri=([^&]+)&(lang=[^&]+) [NC]
RewriteRule lang\.php$ /%1&%2? [L,NE,R=temporary]

【问题讨论】:

  • %2F 不允许在 Apache 中使用,除非您在 Apache 服务器配置中使用了 AllowEncodedSlashes
  • @anubhava 我刚刚在我的开发环境中启用了它,但我仍然得到 404

标签: apache .htaccess redirect mod-rewrite apache2.2


【解决方案1】:

您可以在您的站点根目录 .htaccess 中使用此规则,就在 RewriteEngine On 行下方:

RewriteEngine On

# uri with query string    
RewriteCond %{QUERY_STRING}     (?:^|&)(lang=[^&]+) [NC]
RewriteCond %1##%{QUERY_STRING} (.*)##(?:.*&)?uri=([^?]+)(?:\?|%3F)([^&]+) [NC]
RewriteRule lang\.php$ /%2?%1&%3 [L,NE,R=302]

# uri without query string    
RewriteCond %{QUERY_STRING}     (?:^|&)(lang=[^&]+) [NC]
RewriteCond %1##%{QUERY_STRING} (.*)##(?:.*&)?uri=([^?]+) [NC]
RewriteRule lang\.php$ /%2?%1 [L,NE,R=302]

【讨论】:

  • 谢谢!我必须更改规则,在中间使用问号才能正常工作,如下所示:RewriteRule lang\.php$ /%2\?%1 [L,NE,R=temporary].
  • 其实经过进一步测试,我发现中间的?只适用于没有查询参数的网址,而中间的&只适用于有查询参数的网址。有没有办法同时满足这两种情况?此外,订单也不能保证,所以我先用 uri 复制它以处理它。我希望我不必复制所有这些来处理有无查询参数
  • 好的,我可以进一步调整这些规则。但是您应该使用显示这些新规则集的现有 .htaccess 更新问题。还请为每个规则提供一个示例 URL,以便我可以在修改后测试规则。
  • 我已经修改了我的问题以添加示例 URL 以及我在您的解决方案中使用该规则的尝试。
  • 是的,完全正确。查询参数的顺序可能不同(如所述)。
猜你喜欢
  • 1970-01-01
  • 2021-07-29
  • 2011-09-30
  • 2013-04-07
  • 2021-02-09
  • 2012-07-21
  • 2018-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多