使用 .htaccess 对除一个路径之外的每个 URL 强制使用 SSL

Jon*_*han 2 mod-rewrite .htaccess apache-2.2

我正在尝试为每个 URL 强制执行 SSL,但第一个段除外/preview

http://test.example.com/preview/blah/blah
Run Code Online (Sandbox Code Playgroud)

应该被规则忽略;应该强制所有其他 URL 使用 SSL。我正在使用 CentOS 6.4、Apache 和 CodeIgniter。

我的 .htaccess 文件:

RewriteEngine On
RewriteBase /

RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_URI} !^/preview/
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
Run Code Online (Sandbox Code Playgroud)

通常 CI URL 在被最后一条规则重写之前看起来像这样:

http://test.example.com/index.php?/preview/blah/blah
Run Code Online (Sandbox Code Playgroud)

我试过了:

RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_URI} !^/index.php?/preview/
RewriteCond %{REQUEST_URI} !^/preview/
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Run Code Online (Sandbox Code Playgroud)

那也行不通。我究竟做错了什么?

Luc*_*oed 6

你几乎拥有它。完整的解决方案是:

RewriteEngine On
RewriteBase /

RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_URI} !^/preview
RewriteCond %{QUERY_STRING} !^/preview
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
Run Code Online (Sandbox Code Playgroud)

它失败的原因是http://test.domain.com/preview/blah/blah首先被解析为http://test.domain.com/index.php?/preview/blah/blah并且该 URL 立即再次被重写(htaccess 使用新 URL 循环)。

新 URL (http://test.domain.com/index.php?/preview/blah/blah与您的条件不匹配,因为 ? 之后的部分不被视为 REQUEST_URI 的一部分,而是 QUERY_STRING 的一部分。请参阅http://httpd.apache.org/docs/2.4/en 上的 REQUEST_URI 说明/mod/mod_rewrite.html#rewritecond