.htaccess - 尝试强制 https 时出现“重定向过多”

Posted

技术标签:

【中文标题】.htaccess - 尝试强制 https 时出现“重定向过多”【英文标题】:.htaccess - "Too many redirects" when trying to force https 【发布时间】:2016-08-13 09:16:09 【问题描述】:

我正在尝试强制我的根域的子文件夹 (/bbb/) 始终显示为 https。我的.htaccess 文件也负责页面的扩展。

我已将.htaccess 文件放在我的/bbb/ 文件夹中,但是当我尝试强制连接到 https 时,我得到“重定向过多”,没有它一切正常。

我的代码有什么问题?

Options +FollowSymLinks -MultiViews
Options +Indexes
AcceptPathInfo Off
RewriteEngine on
RewriteBase   /

ErrorDocument 404 https://example.co.uk/404page/404.html

#Force from http to https
RewriteCond %SERVER_PORT 80 
RewriteCond %HTTP_HOST !^bbb.example.co.uk/$
RewriteRule ^(.*)$ https://bbb.example.co.uk/$1 [R=301]

#take off index.html
 RewriteCond %HTTP_HOST !^www\. [NC]
RewriteCond %REQUEST_URI ^(.*/)index\.html$ [NC]
RewriteRule . http://www.%HTTP_HOST%1 [R=301,NE,L]

## hide .php extension
# To externally redirect /dir/foo.php to /dir/foo
RewriteCond %THE_REQUEST ^[A-Z]3,\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R,L,NC]

## To internally redirect /dir/foo to /dir/foo.php
RewriteCond %REQUEST_FILENAME.php -f
RewriteRule ^ %REQUEST_URI.php [L]    

## hide .html extension
# To externally redirect /dir/foo.html to /dir/foo
RewriteCond %THE_REQUEST ^[A-Z]3,\s([^.]+)\.html [NC]
RewriteRule ^ %1 [R,L,NC]

## To internally redirect /dir/foo to /dir/foo.html
RewriteCond %REQUEST_FILENAME.html -f
RewriteRule ^ %REQUEST_URI.html [L]

【问题讨论】:

HTTP_HOST 只包含主机名。你的bbb.example.co.uk/ 永远不会匹配,因为/ 不是主机名的有效部分。 【参考方案1】:

试试这个:

RewriteEngine On
RewriteCond %ENV:HTTPS !on
RewriteRule ^(.*)$ https://%HTTP_HOST%REQUEST_URI [L,R=301]

【讨论】:

更多赞%ENV:HTTPS!不知道为什么或如何,但似乎是唯一适用于我的设置的规则! 如上 - 客户奇怪的托管包,这是唯一有效的规则 是的,工作...但是为什么?!?在过去一年左右的时间里,我们已经将许多客户端切换到 HTTPS,但这是我不得不求助于这个的第一个实例...... 这对我不起作用:-(这可能是我将以下内容放入<Virtualhost: *.80>指令而不是.htaccess的原因?RewriteEngine on RewriteCond %ENV:HTTPS !on RewriteCond %HTTPS !on RewriteRule ^(.*)$ https://%HTTP_HOST%REQUEST_URI [L,R=301] 所以我们说 RewriteCond %SERVER_PORT 80 那时不起作用,它似乎甚至适用于 https 连接,而 RewriteCond %ENV:HTTPS !on 按预期工作。接受的答案被接受,因为它修复了 OP 的错字,但这是真正有用的答案【参考方案2】:

如果您有代理服务器或使用共享主机,那么有时您会通过 CloudFlare 获得免费的 SSL。如果你使用像 CodeIgniter 或 Laravel 这样的框架,那么你总是有一个路由文件。所以有时我上面给出的答案可能不起作用。

在这种情况下,当您尝试重定向到 https 时,您可能会遇到无限循环。因此,要解决这个问题,您可以尝试以下方法:

RewriteEngine On

# If we receive a forwarded http request from a proxy...
RewriteCond %HTTP:X-Forwarded-Proto =http [OR]

# ...or just a plain old http request directly from the client
RewriteCond %HTTP:X-Forwarded-Proto =""
RewriteCond %HTTPS !=on

# Redirect to https version
RewriteRule ^ https://%HTTP_HOST%REQUEST_URI [L,R=301]

【讨论】:

这对我有用!显然 CloudFlare 搞砸了重定向。 在尝试了几乎所有方法之后,这只有效!非常感谢:) 同样,当我尝试使用任何其他方法强制 https 时,CloudFlare 以某种方式导致了重定向循环。很好的解决方案@harshal lonare 太棒了,Cloud Flare 代理似乎是导致无限重定向的问题,非常感谢!【参考方案3】:

问题出在这条规则中:

#Force from http to https
RewriteCond %SERVER_PORT 80 
RewriteCond %HTTP_HOST !^bbb.example.co.uk/$
RewriteRule ^(.*)$ https://bbb.example.co.uk/$1 [R=301]

将此规则更改为:

#Force from http to https
RewriteCond %HTTPS !on 
RewriteCond %HTTP_HOST =bbb.example.co.uk
RewriteRule ^(.*)$ https://%HTTP_HOST/$1 [R=301,L,NE]

由于在开始时使用了!,您的条件被颠倒了,并且在结束时有一个额外的斜线永远不会匹配,因此使您的条件始终返回 true。

确保在测试之前清除浏览器缓存。

【讨论】:

【参考方案4】:

.htaccess 文件中的重定向

.htaccess 文件是一个配置文件,用于修改网站/服务器上每个目录的 Apache 服务器行为。这是一个用户级配置文件,这里只能编辑部分Apache配置,虽然重定向是常用的。

您可以将多个 .htaccess 文件级联到一系列目录中。如果您在父目录中有一个 .htaccess,在子目录中有另一个,它们都会影响子目录。在这些情况下,重要的是要记住您在哪里拥有和不拥有 .htaccess 文件,以防止不同级别的 .htaccess 文件之间发生冲突。

以下是一系列重定向示例,有助于识别 .htaccess 文件中的重定向。这些不是进行此类重定向的唯一方法,但它们应该向您展示最常见的重定向是什么样的,以便您可以识别它们是否在您正在使用的 .htaccess 文件中。

强制 HTTPS 下面的 .htaccess 代码首先检查请求是使用 HTTP 还是 HTTPS 进入服务器的。如果请求未使用 HTTPS,则配置将告诉浏览器重定向到之前请求的同一网站和 URL 的 HTTPS 版本。

RewriteEngine On
 RewriteCond %HTTPS off
 RewriteRule (.*) https://%HTTP_HOST%REQUEST_URI [R=301,L]

强制 HTTPS: 在负载均衡器或代理(CloudFlare/Incapsula/Sucuri/等)后面时 有时您可能正在使用代理,例如负载均衡器或 Web 防火墙,例如 CloudFlare、Incapsula 或 Sucuri。这些可以配置为在前端使用 SSL,但不能在后端使用 SSL。为了使其正常工作,您不仅需要检查请求中的 HTTPS,还需要检查代理是否仅使用 HTTP 将原始 HTTPS 请求传递给服务器。以下规则检查请求是否是从 HTTPS 转发的,如果是,则不会尝试重定向额外的时间。

RewriteEngine On
 RewriteCond %HTTPS off
 RewriteCond %HTTP:X-Forwarded-Proto =http
 RewriteRule (.*) https://%HTTP_HOST%REQUEST_URI [R=301,L]

强制非www 此重定向仅检查是否在域名开头使用 www 请求网站名称。如果包含 www,它会重写请求并告诉浏览器重定向到非 www 版本的域名。

RewriteEngine On
 RewriteCond %HTTP_HOST ^www\. [NC]
 RewriteRule (.*) http://%HTTP_HOST%REQUEST_URI [R=301,L]

强制 www 最后一个重定向检查是否没有在域名开头使用 www 请求网站名称。如果不包含 www,它会重写请求并告诉浏览器重定向到 www 版本的域。

RewriteEngine On
 RewriteCond %HTTP_HOST !^www\. [NC]
 RewriteRule (.*) http://www.%HTTP_HOST%REQUEST_URI [R=301,L]

【讨论】:

【参考方案5】:
RewriteCond %HTTPS off
RewriteCond %HTTP:X-Forwarded-Proto =http
RewriteRule ^(.*)$ https://%HTTP_HOST%REQUEST_URI [L,R=301]

Add X-Forwarded-Proto condition instead

【讨论】:

【参考方案6】:

受this 答案的启发,我在 Cloudflare 的 WAF 之后保护了我的域。在域的 Cloudflare 仪表板中,在 SSL/TSL 选项卡上,我使用 Flexible SSL/TSL 加密设置,即在浏览器和 cloudflare 之间加密流量,但未加密与我的服务器完全端到端。此设置中的某些问题导致重定向过多。

无需对我的 apache 配置或 htaccess 文件进行任何额外编辑的解决方案就是将设置更改为“Full”。这会加密端到端并立即解决重定向问题。

【讨论】:

以上是关于.htaccess - 尝试强制 https 时出现“重定向过多”的主要内容,如果未能解决你的问题,请参考以下文章

通过 htaccess 强制非 www 和 https

.htaccess:在所有页面上强制 www,在一个页面上强制 https,在所有其他页面上强制 http

markdown 强制HTTPS #htaccess #https #security

zf2 - 使用 .htaccess 强制 SSL/https

使用 .htaccess 对子域强制使用 SSL HTTPS

如何使用 htaccess 强制 http-NOT https