在维护协议 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_HOSTHTTPS 两个值。重要的是,# 本身不能出现在这两个值中。 (?: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的主要内容,如果未能解决你的问题,请参考以下文章

如何同时使用http和https协议

Spring Boot项目如何同时支持HTTP和HTTPS协议

如何让http 和https 同时使用

HTTPS那些协议:TLS, SSL, SNI, ALPN, NPN

apache怎么一个端口同时用于http和https

「offer来了」浏览器原理被问懵?5大知识板块巩固你的http知识体系(3.6w字)