Apache HTTP 服务器是世界上最流行的 Web 服务器之一。它是一个开源且跨平台的 HTTP 服务器,为互联网上很大一部分网站提供支持。Apache 提供了许多强大的功能,可以通过额外的模块进行扩展。

如果您是网站所有者或系统管理员,您很可能经常与 Apache 打交道。您最常执行的任务之一可能是将 HTTP 流量重定向到您网站的安全 (HTTPS) 版本。

与以明文发送和返回请求与响应的 HTTP 不同,HTTPS 使用 TLS 来加密客户端与服务器之间的通信。

与 HTTP 相比,使用 HTTPS 有许多优势,例如:

  • 所有数据在双向传输时都会被加密。因此,即使敏感信息被拦截也无法读取。
  • 现代浏览器会为 HTTP 网站显示“不安全”警告。
  • HTTPS 允许您使用 HTTP/2 协议,这能显著提升网站性能。
  • Google 青睐 HTTPS 网站。如果通过 HTTPS 提供服务,您的网站排名会更好。

本指南介绍如何在 Apache 中将 HTTP 流量重定向到 HTTPS。

在设置重定向之前,您需要一个有效的 SSL/TLS 证书。Let’s Encrypt提供免费证书,是大多数网站最常用的选择。对于外部访问者无法访问的暂存站点或内部站点,自签名证书也同样适用。

在 Apache 中有多种重定向到 HTTPS 的方法。如果您对运行 Apache 的 Linux 服务器拥有 root 访问权限,首选方法是在域名的虚拟主机配置文件中设置重定向。否则,您可以在域名的 .htaccess 文件中设置重定向。某些控制面板(例如 cPanel)允许您通过点击几下鼠标来强制 HTTPS 重定向。

使用虚拟主机将 HTTP 重定向到 HTTPS

Apache 虚拟主机定义了服务器上托管的一个或多个域名的设置。在虚拟主机指令中,您可以指定站点文档根目录(包含网站文件的目录)、为每个站点创建单独的安全策略、使用不同的 SSL 证书、配置重定向等。

通常,当在某个域名上安装 SSL 证书后,该域名会有两个虚拟主机指令。第一个用于端口 80 上的 HTTP 版本站点,另一个用于端口 443 上的 HTTPS 版本。

在基于 Red Hat 的发行版(如 CentOS和 Fedora)中,虚拟主机文件存储在 /etc/httpd/conf.d 中。在 Debian 及其衍生版(如 Ubuntu)中,这些文件存储在 /etc/apache2/sites-available 目录中。

在添加重定向之前,请确保该域名拥有有效的 TLS 证书,并且 HTTPS 虚拟主机正常工作。

要将网站重定向到 HTTPS,请使用 Redirect 指令,如下例所示:

<VirtualHost *:80> 
  ServerName example.com
  ServerAlias www.example.com

  Redirect permanent / https://example.com/
</VirtualHost>

<VirtualHost *:443>
  ServerName example.com
  ServerAlias www.example.com

  Protocols h2 http/1.1

  # SSL Configuration

  # Other Apache Configuration

</VirtualHost>

让我们解释一下这段代码。我们有两个虚拟主机指令,一个用于站点的 HTTP 版本,另一个用于 HTTPS 版本。

  • VirtualHost *:80 - Apache 服务器监听指定域名在端口 80 (HTTP) 上的传入连接。
  • VirtualHost *:443 - Apache 服务器监听指定域名在端口 443 (HTTPS) 上的传入连接。

ServerName 和 ServerAlias 指令指定虚拟主机的域名。请确保将它们替换为您的域名。

高亮显示的行 Redirect permanent / https://example.com/ 位于 HTTP 虚拟主机内,用于将流量重定向到站点的 HTTPS 版本。

通常您还希望将站点的 HTTPS www 版本重定向到非 www 版本,或者反之。以下是一个示例配置:

<VirtualHost *:80> 
  ServerName example.com
  ServerAlias www.example.com

  Redirect permanent / https://example.com/
</VirtualHost>

<VirtualHost *:443>
  ServerName example.com
  ServerAlias www.example.com

  Protocols h2 http/1.1

  <If "%{HTTP_HOST} == 'www.example.com'">
    Redirect permanent / https://example.com/
  </If>

  # SSL Configuration

  # Other Apache Configuration

</VirtualHost>

HTTPS 虚拟主机内的代码(高亮显示的行)会检查请求头是否包含 www 域名,并重定向到非 www 版本。

如果 HTTPS 虚拟主机未配置或证书缺失,重定向可能会导致循环或浏览器错误。在强制实施重定向之前,请确保 HTTPS 正常工作。

每当您更改配置文件时,都需要重启或重新加载 Apache 服务以使更改生效:

  • Debian 和 Ubuntu:

    sudo systemctl reload apache2
  • CentOS 和 Fedora:

    sudo systemctl reload httpd

使用 .htaccess 将 HTTP 重定向到 HTTPS

.htaccess 是 Apache Web 服务器基于每个目录的配置文件。此文件可用于定义 Apache 如何从放置该文件的目录中提供文件,以及开启或关闭附加功能。

通常,.htaccess 文件放置在域名根目录中,但您也可以在其他子目录中拥有其他 .htaccess 文件。

此方法要求 Apache 服务器上加载了 mod_rewrite 模块。大多数服务器默认加载此模块。如果可能,优先在虚拟主机中创建重定向,因为它更简单也更安全。

要将所有 HTTP 流量重定向到 HTTPS,请打开根目录中的 .htaccess 文件并向其中添加以下代码:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]

以下是这段代码的含义:

  • RewriteEngine On - 启用重写功能。
  • RewriteCond %{HTTPS} off - 检查是否为 HTTP 连接,如果条件满足,则执行下一行。
  • RewriteRule ^(.*)$ https://example.com/$1 [L,R=301] - 使用状态码 301(永久移动)将 HTTP 重定向到 HTTPS。请确保更改域名。

下面的示例有一个附加条件,用于检查请求是否以 www 开头。使用它可强制所有访问者使用 HTTPS 非 www 版本的站点:

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

编辑 .htaccess 文件时,您无需重启服务器,因为 Apache 会在每次请求时读取该文件。

重定向到单一规范主机

如果您想将所有流量强制到单一主机(www 或非 www),请在 HTTPS 虚拟主机上使用规范重定向。例如,要将所有流量重定向到非 www 版本:

<VirtualHost *:443>
  ServerName example.com
  ServerAlias www.example.com

  <If "%{HTTP_HOST} == 'www.example.com'">
    Redirect permanent / https://example.com/
  </If>

  # SSL Configuration
</VirtualHost>

测试重定向

使用 curl 验证 HTTP 请求是否重定向到 HTTPS:

curl -I http://example.com

您应该会看到一个 301 响应以及一个指向 HTTPS URL 的 Location 头:

HTTP/1.1 301 Moved Permanently
Location: https://example.com/

启用 HSTS(HTTP 严格传输安全)

HSTS 告诉浏览器在连接到您的站点时始终使用 HTTPS,即使用户在地址栏中输入 http://。这可以防止降级攻击并提高安全性。

将以下头添加到您的 HTTPS 虚拟主机中:

<VirtualHost *:443>
  ServerName example.com

  Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

  # SSL Configuration
</VirtualHost>

max-age 值以秒为单位。上面的示例将其设置为一年(31536000 秒)。includeSubDomains 指令会将策略应用于所有子域名。

要使用 Header 指令,必须启用 mod_headers 模块。在 Debian/Ubuntu 上,运行:

sudo a2enmod headers
sudo systemctl reload apache2

故障排除

重定向循环

如果您的浏览器显示“重定向过多”,请检查:

  • HTTPS 虚拟主机已正确配置并监听端口 443
  • SSL 证书有效且未过期
  • 您没有在配置中将 HTTPS 重定向到 HTTPS

混合内容警告

启用 HTTPS 后,如果某些资源(图像、脚本、CSS)仍通过 HTTP 加载,您的站点可能会显示混合内容警告。请将所有内部链接更新为使用 HTTPS,或使用协议相对 URL(//example.com/path)。

更改未生效

如果对虚拟主机配置的更改没有生效,请确保已重新加载 Apache:

终端
sudo systemctl reload apache2  # Debian/Ubuntu
sudo systemctl reload httpd    # CentOS/Fedora

对于 .htaccess 的更改,请确认虚拟主机配置中的 AllowOverride 已设置为 All。

快速参考

方法使用场景
虚拟主机重定向当您拥有服务器访问权限时的首选方法
.htaccess 重定向当您无权访问虚拟主机配置时
HSTS 头在重定向正常工作后添加,以提高安全性