.htaccess 重定向到 https://www

332

我有以下的htaccess代码:

<IfModule mod_rewrite.c>

RewriteEngine On
RewriteCond !{HTTPS} off
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

</IfModule>

我希望我的网站在使用HTTPS的情况下重定向到https://www.,并强制使用www.子域名, 但当我访问http://www.(未使用HTTPS)时,它不会将我重定向到https://www


应该是 RewriteCond %{HTTPS} =off - Michael Berkowski
1
如果我这样做,它会重定向到 h t t p s : / / w w w.w w w. - bigben
亲爱的@bigben,你在这里接受了一个错误的答案!你可以在我的回答中找出为什么它是错误的。 - Amir Fo
还可以查看这个“在一个单一的301重定向中强制执行httpswww” https://helponnet.com/2021/03/23/http-to-https-and-enforce-www-in-one-301-redirect-on-htaccess/ - Amit Verma
14个回答

667
要强制使用HTTPS,您需要检查正确的环境变量%{HTTPS} off,但是您上面的规则会在前面添加www.。由于您有第二个规则来强制使用www.,因此不要在第一个规则中使用它。
RewriteEngine On
RewriteCond %{HTTPS} off
# First rewrite to HTTPS:
# Don't put www. here. If it is already there it will be included, if not
# the subsequent rule will catch it.
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Now, rewrite any request to the wrong domain to use www.
# [NC] is a case-insensitive match
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

关于代理

在某些形式的代理中,客户端通过HTTPS连接到代理、负载均衡器、Passenger应用程序等,%{HTTPS}变量可能永远不会是on,从而导致重写循环。这是因为您的应用程序实际上接收的是纯HTTP流量,即使客户端和代理/负载均衡器使用HTTPS。在这种情况下,请检查X-Forwarded-Proto头,而不是%{HTTPS}变量。此答案显示了适当的处理过程


155

Michals的答案对我有用,尽管稍作修改:

问题:

当您拥有单个站点安全证书时,试图访问您的页面而没有 https://www. (或任何您证书覆盖的域名) 的浏览器将在甚至到达接收重定向到安全和正确的 https 页面之前显示一个丑陋的红色警告屏幕。

解决方案:

首先使用重定向到 www(或由您的证书覆盖的任何域),然后再执行 https 重定向。这将确保您的用户不会因为浏览器看到不覆盖当前网址的证书而遇到任何错误。

#First rewrite any request to the wrong domain to use the correct one (here www.)
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

#Now, rewrite to HTTPS:
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

101

如果您正在使用CloudFlare或类似的CDN,使用此处提供的 %{HTTPS} 解决方案可能会导致无限循环错误。如果您是CloudFlare用户,您需要使用以下解决方案:

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

67

不好的解决方案及原因

绝对不要使用以下的解决方案,因为当你使用他们的代码时,会出现类似以下的问题:

RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.example.com%{REQUEST_URI} [L,R=301]

浏览器跳转到:

http://example.com

然后重定向到:

https://example.com

然后重定向到:
https://www.example.com

这是对服务器的请求太多了。

大多数答案,即使被接受的答案也存在这个问题。


最佳解决方案

此代码具有[OR]条件,以防止在URL上进行双重更改!

RewriteEngine on
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule (.*) https://www.example.com%{REQUEST_URI} [R=301,L]

4
“错误的解决方案及原因!”- 那些规则的顺序是错误的。将这两条规则颠倒一下,就会正确了 - 你只会得到一个重定向而不是两个。 - MrWhite
6
是的,按照给定的代码会产生2次重定向 - 我不会质疑这一点 - 我只是想说你只需要反转这些规则就可以解决这个问题,不需要做其他修改。(“被接受”的答案确实是错误的 - 这似乎是你所指的 - 这些指令的顺序是错误的。) - MrWhite
1
是的,@AmirForsati是正确的。它重定向了两次,这应该是被接受的答案。 - Zakir hussain
4
如果您想保留域名变量,可以使用以下代码:RewriteEngine On RewriteCond %{HTTPS} off RewriteCond %{HTTP_HOST} !^www\. [NC] RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] RewriteCond %{HTTPS} off RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]注:以上内容为Apache服务器的重写规则,用于实现在网站访问时自动将未加密的HTTP连接转向加密的HTTPS连接。其中 "%{HTTP_HOST}%{REQUEST_URI}" 表示当前请求的完整URL地址,"R=301" 表示执行永久重定向。 - I.devries
1
第一种解决方案并不一定“糟糕”,实际上,如果您正在实现HSTS,那么这是_正确的_解决方案。在这种情况下,您需要先从HTTP重定向到HTTPS _在同一主机上_,然后再将主机名规范化(即将非www重定向到www)。当实现HSTS时,您无法避免潜在的双重重定向,但这只是一个边缘情况,并且仅在用户的第一次访问时发生(在保存HSTS凭据之前)。 - MrWhite
显示剩余2条评论

40

这是我为代理和非代理用户找到的最佳方式

RewriteEngine On

### START WWW & HTTPS

# ensure www.
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# ensure https
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

### END WWW & HTTPS

2
这是我发现的最好的代理和非代理用户的方法。+1 - Deep 3015
1
这是最好的解决方案,因为它可以解决多个301重定向问题。 - Niraj Chauhan
2
有史以来最好的解决方案。 - S M Jobayer Alam
1
很棒的答案。这是唯一一个对我有用的。适用于在Cloudflare后面的情况(尽管我在Cloudflare上没有设置页面规则)。 - jasonco
适用于我所有情况的唯一解决方案。 但是如果我想做相反的事情并删除所有的“www。”呢? - FedeKrum

28

现在有很多解决方案。这里是一个直接处理此问题的Apache Wiki链接。

http://wiki.apache.org/httpd/RewriteHTTPToHTTPS

RewriteEngine On
# This will enable the Rewrite capabilities

RewriteCond %{HTTPS} !=on
# This checks to make sure the connection is not already HTTPS

RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
# This rule will redirect users from their original location, to the same location but using HTTPS.
# i.e.  http://www.example.com/foo/ to https://www.example.com/foo/
# The leading slash is made optional so that this will work either in httpd.conf
# or .htaccess context

12

要将http://https://重定向到https://www,您可以在所有版本的Apache上使用以下规则:

RewriteEngine on

RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.example.com%{REQUEST_URI} [NE,L,R]

Apache 2.4

RewriteEngine on

RewriteCond %{REQUEST_SCHEME} http [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.example.com%{REQUEST_URI} [NE,L,R]

请注意,自Apache2.4开始,变量%{REQUEST_SCHEME}可供使用。


8
如果您正在使用CloudFlare,请确保使用类似于以下的内容。
# BEGIN SSL Redirect
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
# END SSL Redirect

这将帮助您避免重定向循环并安全地将您的站点重定向到SSL。
附:检查mod_rewrite.c是个好主意!

它不会将 https://theurlwithoutwww.com 重定向到 https://www. - thesearentthedroids
如果您事先有一些“添加www”指令,那么这实际上是唯一有效的解决方案。其他解决方案会给我带来“重定向太多”的问题。 - Daniel.P.

4
RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R]

2
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]

注意:请确保您已完成以下步骤

  1. 运行sudo a2enmod rewrite命令
  2. 运行sudo service apache2 restart命令
  3. 在位于/etc/apache2/sites-available/000-default.conf的虚拟主机文件中添加以下内容
<Directory /var/www/html>
  Options Indexes FollowSymLinks MultiViews
  AllowOverride All
  Order allow,deny
  allow from all
  Require all granted
</Directory>

现在你的 .htaccess 将生效,你的网站将重定向到 https://www

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接