我有这些.htaccess
规则:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST} [R=301,L]
在主域上将 HTTP 重定向到 HTTPS 并将非 www 重定向到 www 时,它工作正常,但如果用户直接转到特定 URL,我希望使用完整的 URL 路径重定向到 https、www。
例如:
http://example.com/login
应该重定向到https://www.example.com/login
http://www.example.com/login
应该重定向到https://www.example.com/login
https://example.com/login
应该重定向到https://www.example.com/login
使用当前设置,它只会重定向到https://www.example.com
或https://www.example.com/index.php
,我该如何实现?
答案1
正如@GeraldSchneider 在评论中提到的那样,您的指令顺序错误。外部重定向(HTTP 到 HTTPS 和非 www 到 www)需要转前你的前端控制器,否则它们将永远不会被处理,除了实际的文件请求。(你的前端控制器将所有未知请求路由到,index.php
然后停止。
但是,您的重定向也是不正确的。您缺少来自代换,因此它们总是会重定向回文档根目录。
因此,请尝试以下操作:
RewriteEngine On
# Front-controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
# HTTP to HTTPS redirect
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]
# Non-www to www redirect
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule (.*) http://www.%{HTTP_HOST}/$1 [R=301,L]
关于上述指令的说明:
(.*)
在前端控制器中,如果 URL 路径(即)没有被使用,则无需捕获它。代换。QSA
这里也不需要标志 - 默认情况下会附加来自请求的查询字符串。$1
请注意RewriteRule
替代- 这是对从请求中捕获的 URL 路径的反向引用(即“完整 URL”)。这在您的两次重定向中都缺失。- 您缺少
[R=301,L]
从 HTTP 到 HTTPS 重定向的标志。如果不明确说明状态代码,这将导致临时 302 重定向,并且重写将继续。如果您打算稍后实施 HSTS,则这些重定向需要分开。
但是,如果您有权访问服务器配置并且不打算实施 HSTS,那么请参考@HBruijn 的回答。
答案2
理想情况下,您可以访问服务器配置,然后您不需要从文件进行重定向.htaccess
,而您的重定向将成为教科书案例在配置特定 VirtualHost 条目上的重定向时,何时不使用 mod_rewrite。
<VirtualHost *:80>
# Redirect http://[www.]example.com/login to https://www.example.com/login
ServerName www.example.com
ServerAlias example.com
Redirect "/" "https://www.example.com/"
</VirtualHost>
<VirtualHost *:443>
# Redirect https://example.com/login to https://www.example.com/login
ServerName example.com
Redirect "/" "https://www.example.com/"
</VirtualHost>
<VirtualHost *:443>
ServerName www.example.com
DocumentRoot /var/www/...
....
</VirtualHost>