【问题标题】:RewriteCond REQUEST_URI - ^ doesn't work as expectedRewriteCond REQUEST_URI - ^ 没有按预期工作
【发布时间】:2012-09-10 01:23:22
【问题描述】:

我正在使用 codeigniter 构建一个站点。我在 .htaccess 文件中有一系列重写条件和规则。第一组规则根据 uri 的第一段打开或关闭 SSL。

然后它再次循环,如果找到匹配项,则适当地重定向页面。如果不匹配,并且 uri 不以列出的任何字符串开头,它会将您重定向到另一个页面。如果不满足条件,则进入索引页面。

问题在于我的第一组打开和关闭 SSL 的规则。我想指定 uri 必须以管理员或安全方式开始。但是如果我将 ^ 添加到字符串的开头,一切都会中断。这是我所拥有的:

RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/?(admin|secure)
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

RewriteCond %{HTTPS} on 
RewriteCond %{REQUEST_URI} !^/?(admin|secure)
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [R=301,L]

...specific rewrites here
RewriteRule ^secure-form1$ secure/contract/secure-form1 [L]
RewriteRule ^secure$ secure/article/secure [L]

RewriteCond %{HTTP_HOST} ^www.example.com$ 
RewriteCond %{REQUEST_URI} !^/(admin|form|secure|page)/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/page/article/$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]

如果我在前 2 个重写条件(https 开启和关闭)中保留 ^ 符号,那么 http://www.example.com/secure 重写为 https://www.example.com/index.php/secure/article/secure 这是最后的重写规则。 url 实际上在浏览器中变成了这个。

如果我从前 2 个重写条件中取出 ^ 符号,那么它会转到正确的页面。但我确实需要指定 uri 的开头,因为在 uri 中间(并在斜线后面)有其他页面不应该使用 SSL。

这个我想不通。

【问题讨论】:

  • 你确定你的 php 代码中没有重定向吗?

标签: regex codeigniter mod-rewrite


【解决方案1】:

试试这个:

RewriteCond %{HTTPS} off 
RewriteCond %{HTTP_HOST} ^(.*)$ 
RewriteRule ^/?(admin|secure)$ https://%1/$1 [R=301,L]

【讨论】:

  • 是的!太感谢了!我没想过要那样做。它现在按预期工作。
【解决方案2】:

老问题,我知道,但如果您真的想坚持 %{REQUEST_URI} 条件,还有另一种解决方案可能会更好:

RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_URI} ^/?(admin|secure)$
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

与 OP 的主要区别在于包含 /? 以检查 URI 开头是否存在正斜杠。 AFAIK,不同的 Apache 安装可能包括也可能不包括 %{REQUEST_URI} 中的斜线。

这样做的一个好处是您可以将规则应用于多个条件:

RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_URI} ^/?admin$ [OR]
RewriteCond %{REQUEST_URI} ^/?secure$ [OR]
RewriteCond %{REQUEST_URI} ^/?top-secret$
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

就我认为的方式而言,这比使用一长串以管道分隔的字符串更容易处理。与单个正则表达式相比,这是以潜在的效率损失为代价的,但您可以进行一些其他改进来抵消这一点:

  • 使用 lexographically equal 运算符!=on。如果您只使用off,它将被视为正则表达式。

  • 消除 RewriteRule 模式,将其替换为单个插入符号,然后使用环境变量 %{HTTP_HOST}%{REQUEST_URI}。这节省了较长的正则表达式模式以及反向引用的开销。

【讨论】:

  • 正如您所写,“不同的 Apache 安装可能会或可能不会在 %{REQUEST_URI} 中包含开始斜杠”。所以如果不是,那么你的代码是错误的,因为%{HTTP_HOST}%{REQUEST_URI} 不会包含任何斜线分隔符。
  • 很好的答案。不过有一个小问题。您提到 REQUEST_URI 可能包含也可能不包含开头的正斜杠。因此,在重建 URL 时依赖包含它似乎是不寻常的。将斜杠显式添加到重定向 URL 似乎更好,并可能在 RewriteRule 或其他不依赖 REQUEST_URI 的解决方案(包括斜杠)中捕获路径,因此您的整个解决方案涵盖了这两种设置。目前,如果 REQUEST_URI 中没有斜杠,重定向 URL 将被破坏,将主机与 URI 和没有斜杠合并。谢谢。
  • 这些是@Ωmega 和@NigelPeck 关于丢失斜线的好点。我想我在想,一旦您确定了环境的需求,就可以添加斜线。如果您绝对需要支持这两种情况,一个简单的解决方法是在重写路径中简单地包含斜杠,因为www.example.com//top-secret 是一个有效的 URI。
猜你喜欢
  • 1970-01-01
  • 2021-10-19
  • 2020-03-18
  • 2012-06-14
  • 2014-11-15
  • 1970-01-01
  • 2012-07-02
  • 2011-09-07
  • 2013-03-03
相关资源
最近更新 更多