我正在尝试配置 apache 服务器,以便将非 www 重定向到 www,将 http 重定向到 https。这是我的配置:
000-默认.conf:
<VirtualHost *:80>
ServerName www.example.com
ServerAlias example.com
# non-www to www
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [END,R=301,L]
DocumentRoot /var/www/...
# to https
RewriteCond %{SERVER_NAME} =example.com [OR]
RewriteCond %{SERVER_NAME} =www.example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
</VirtualHost>
000-默认-le-ssl.conf:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName www.example.com
ServerAlias example.com
# non-www to www
RewriteEngine On
RewriteCond %{HTTP_HOST} (?!^www\.)^(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L]
DocumentRoot /var/www/...
SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
问题是,当我访问时https://example.com
,它不会重定向,而是显示一个错误,说证书的所有者与主机名“example.com”不匹配。为什么它没有从 重定向https://
到https://www.
?
答案1
当您从 Let's Encrypt 获取 SSL 证书时,您是否只为“www.example.com”获取了证书?Let's Encrypt 客户端(例如 certbot)仅为您请求的明确域名提供证书。
您看到的消息是您的浏览器正在接收不匹配的域名的 SSL 证书。
在将重定向发送到您的浏览器之前,对于 SSL 站点,您的浏览器必须在其自身和服务器之间创建一个安全隧道。作为该过程的一部分,服务器会发送证书,在本例中,
SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem
如果该证书包含您访问网站时使用的域名,则一切正常,您的浏览器将继续,并且网络服务器将向您发送重定向响应。如果不匹配,浏览器会认为有人在搞鬼,并抛出错误消息。
如果我对问题的猜测正确的话,最简单的做法是使用 certbot 申请一个额外的域名 example.com和www.example.com。它可能会说“此证书已存在,您是否要扩展”(或类似内容),回答是。无论如何,请确保新证书已配置为由 Apache 提供服务。
需要注意的是,您不需要从 http 重定向到 https 两次,也不需要从 www 重定向到 www。您的 :80 配置可以简化为;
RewriteEngine on
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L,QSA]
我倾向于使用下面的方法,因为它更短:
RewriteEngine on
RewriteRule ^(.*)$ https://www.example.com$1 [R=301,L,QSA]
答案2
证书检查在您的服务器收到请求之前完成。它在向服务器提交请求之前设置 TLS 连接期间进行。
如果您接受连接,则会发生重定向。
或者,将 example.com 作为主题备用名称添加到证书中,这样无需用户干预即可成功连接。如果选择此选项,请添加您预计会使用的所有域名。
答案3
不确定这是否适合您,但这就是我所拥有的并且有效:
ServerName www.example.com
ServerAlias example.com
...
...
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.example.com [OR]
RewriteCond %{SERVER_NAME} =example.com
RewriteRule ^ https://www.example.com%{REQUEST_URI} [END,NE,R=permanent]