在维护协议 HTTP 或 HTTPS 的同时将 www 重定向到非 www
Posted
技术标签:
【中文标题】在维护协议 HTTP 或 HTTPS 的同时将 www 重定向到非 www【英文标题】:Redirecting www to non-www while maintaining the protocol HTTP or HTTPS 【发布时间】:2015-07-28 06:00:41 【问题描述】:我正在尝试为 HTTP 和 HTTPS 请求将 www 重定向到非 www。我的根 .htaccess 看起来像这样:
RewriteEngine on
RewriteCond %HTTP_HOST ^www.example.com$
RewriteRule ^(.*)$ http://example.com/$1 [R=301]
RewriteCond %HTTP_HOST ^www.example.com$
RewriteCond %SERVER_PORT ^443
RewriteRule ^(.*)$ https://example.com/$1 [R=301]
这并没有完全按预期工作。会发生什么:
访问http://www.example.com
会导致重定向到http://example.com
。这表明我的第一个规则和条件有效,mod_rewite 模块是 hunky-dory 并且 .htaccess 已启用。
访问https://www.example.com
不会导致重定向。我留在https://www.example.com
我的问题
为了使上述重写规则起作用,我的服务器必须有 SSL 证书吗?它目前没有,我想知道这是否是事情不工作的原因。
【问题讨论】:
不要认为你需要两个规则...你只是检查HTTP_HOST
是否存在www.
。它也应该适用于 HTTPS。
@MikeRockett 是的,但您需要将协议 http|https
显式添加到重写目标。我不确定处理这个问题的动态方法是什么。
@RahilWazir - 当然,那是有道理的。
@MikeRockett 是的,第一条规则的目标就是问题所在。例如。如何避免对 http 或 https 部分进行硬编码?
【参考方案1】:
受@MikeRockétt 回答的启发,这是一个“简化”版本,仅使用一个条件(而不是三个)。这也规范了 FQDN(即通过删除主机名上的可选尾随点):
RewriteEngine On
RewriteCond %HTTP_HOST#%HTTPSs ^www\.(.+?)\.?#(?:on(s)|)
RewriteRule ^ http%2://%1%REQUEST_URI [R=301,L]
此 301 将 www 重定向到非 www,同时保持相同的协议、HTTP 或 HTTPS。可以在.htaccess
(目录上下文)或主服务器配置/虚拟主机中原样使用。 (不过,如果您在 virtualhost 上下文中,您可能应该改用更简单的 mod_alias Redirect
。)
说明:
TestString %HTTP_HOST#%HTTPSs
(计算结果为“www.example.com#ons”形式的字符串)与 CondPattern ^www\.(.+?)\.?#(?:on(s)|)
对于Host
标头以“www.”开头的任何请求,条件都是成功的。
^www\.(.+?)\.?
首先检查Host
是否以“www”开头。 (如果没有,它会提前失败)并捕获 %1
反向引用中剩余的主机头(不包括可选的尾随点)。捕获域名的正则表达式,即。 (.+?)
是非贪婪的,因此它不会在末尾捕获可选的点。
#
只是一个任意字符,用于分隔 HTTP_HOST
和 HTTPS
两个值。重要的是,#
本身不能出现在这两个值中。
(?:on(s)|)
是一个非捕获组,它使用 alternation 来匹配 %HTTPSs
。它要么匹配 on(s)
并捕获“s”(在 %2
反向引用中),要么匹配 anything 并且不捕获任何内容(因此 %2
为空)。
如果前面的条件成功,则评估 substitution 字符串 (http%2://%1%REQUEST_URI
) 并重定向请求。来自前面的CondPattern 的反向引用%2
或者包含一个“s”(在替换中制作“https”)或者为空(即“http” ) 和%1
是主机名减去“www”。前缀。
REQUEST_URI
服务器变量保存完整的 URL 路径,包括斜杠前缀。
我的服务器必须有 SSL 证书吗?
是的,否则 浏览器 将阻止连接(抱怨安全证书无效) - 或者只是超时(因为您的服务器在端口 443 上没有响应)并且请求甚至不会到达您的服务器。
【讨论】:
【参考方案2】:第一条规则优先于https
请求,因为它只是满足了重写条件。第一条规则基本上告诉匹配域,你可以让你的重写开始。而是添加另一个条件来判断它是否不是 https
请求
所以试试这个:
RewriteEngine on
RewriteCond %HTTP_HOST ^www.example.com$
RewriteCond %SERVER_PORT !^443
RewriteRule ^(.*)$ http://example.com/$1 [L,R=301]
RewriteCond %HTTP_HOST ^www.example.com$
RewriteCond %SERVER_PORT ^443
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]
https
协议需要 ssl 证书才能工作
我还添加了 [L]
标志,告诉不要处理进一步的规则
【讨论】:
您描述的逻辑听起来不错,但是当我复制并粘贴到我的 .htaccess 并请求https://www.example.com
时,两个规则都失败了。第一条规则预计会失败,但第二条规则应该有效。我必须有证书才能使用它吗?
@henrywright 当然你需要ssl证书请阅读security.stackexchange.com/a/38592/35190
但是如果没有证书,redirect 是否仍然可以工作?我知道如果我没有证书,我会收到警告,但重定向应该仍然发生吗?
谢谢,但我不明白你的意思?
啊,我们开始了。这回答了我的问题:***.com/a/6331410/1709033【参考方案3】:
也许您可以尝试以下方法:
RewriteEngine on
# Check if the host contains "www."
RewriteCond %HTTP_HOST ^www\.
# Check if we're using HTTPS
RewriteCond %HTTPSs ^on(s)|off
RewriteCond http%1://%HTTP_HOST ^(https?://)(www\.)?(.+)$
# Redirect accordingly
RewriteRule ^ %1%3%REQUEST_URI [R=301,L]
【讨论】:
Rahil Wazir 的解决方案在我使用 .htaccess 检查器(例如 htaccess.madewithlove.be)进行测试时有效。问题是它不适用于我的安装。我想知道为什么。我怀疑我需要 SSL 证书才能使重定向工作,但我无法确定? 不错的解决方案 (+1),但是,它可以简化为仅 1 个条件。见my answer below。以上是关于在维护协议 HTTP 或 HTTPS 的同时将 www 重定向到非 www的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot项目如何同时支持HTTP和HTTPS协议