htaccess https 太多重定向不适用于特定主机

htaccess https too many redirects works not on specific hosting

我想通过 htaccess 强制将 HTTP 重定向到 HTTPS。当然,我在这里寻找了大量的解决方案,但没有任何帮助。在其他主机上,此解决方案有效但不适用于此处。

如果我这样尝试:

RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

它会重定向到 HTTPs,但随后它说页面不工作,重定向太多。

但我的 htaccess 中没有更多内容,为什么重定向太多?

另一种无效的解决方案:

RewriteCond %{HTTP:HTTPS} !on  [OR]
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule (.*) https://www.example.com/ [R=301,QSA]

这是 $_SERVER 的转储:

HTTP:

PHP_FCGI_CHILDREN:  0
SCRIPT_NAME:    /test2.php
REQUEST_URI:    /test2.php
QUERY_STRING:   
REQUEST_METHOD: GET
SERVER_PROTOCOL:    HTTP/1.0
GATEWAY_INTERFACE:  CGI/1.1
REDIRECT_URL:   /test2.php
REMOTE_PORT:    50086
SCRIPT_FILENAME:    /hosting/www/.../test2.php
SERVER_ADMIN:   admin@...
REQUEST_SCHEME: http
DOCUMENT_ROOT:  /hosting/www/example.com/
REMOTE_ADDR:    178.41.4.145
SERVER_PORT:    80
SERVER_ADDR:    178.238.37.248
SERVER_NAME:    www.example.com
SERVER_SOFTWARE:    Apache
SERVER_SIGNATURE:   
HTTP_ACCEPT_LANGUAGE:   sk,en;q=0.9,en-GB;q=0.8,en-US;q=0.7,cs;q=0.6
HTTP_ACCEPT_ENCODING:   gzip, deflate
HTTP_ACCEPT:    text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
HTTP_USER_AGENT:    Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.50
HTTP_UPGRADE_INSECURE_REQUESTS: 1
HTTP_CACHE_CONTROL: max-age=0
HTTP_CONNECTION:    close
HTTP_HOST:  www.example.com
HTTP_AUTHORIZATION: 
BACKEND_NAME:   httpd1
HOSTNAME:   lucy.onebit.cz
UNIQUE_ID:  Yg_Luo5QXSFkFIZSmZji5AAAAMk
REDIRECT_STATUS:    200
REDIRECT_BACKEND_NAME:  httpd1
REDIRECT_HOSTNAME:  lucy.onebit.cz
REDIRECT_UNIQUE_ID: Yg_Luo5QXSFkFIZSmZji5AAAAMk
PHP_SELF:   /test2.php
REQUEST_TIME_FLOAT: 1645202362.2178
REQUEST_TIME:   1645202362
URL:    /test2.php
STATUS: 200

HTTPS:

PHP_FCGI_CHILDREN:  0
SCRIPT_NAME:    /test2.php
REQUEST_URI:    /test2.php
QUERY_STRING:   
REQUEST_METHOD: GET
SERVER_PROTOCOL:    HTTP/1.0
GATEWAY_INTERFACE:  CGI/1.1
REDIRECT_URL:   /test2.php
REMOTE_PORT:    51668
SCRIPT_FILENAME:    /hosting/www/example.com/www/test2.php
SERVER_ADMIN:   admin@...
REQUEST_SCHEME: http
DOCUMENT_ROOT:  /hosting/www/example.com/
REMOTE_ADDR:    178.41.4.145
SERVER_PORT:    443
SERVER_ADDR:    178.238.37.248
SERVER_NAME:    www.example.com
SERVER_SOFTWARE:    Apache
SERVER_SIGNATURE:   
HTTP_ACCEPT_LANGUAGE:   sk,en;q=0.9,en-GB;q=0.8,en-US;q=0.7,cs;q=0.6
HTTP_ACCEPT_ENCODING:   gzip, deflate, br
HTTP_SEC_FETCH_DEST:    document
HTTP_SEC_FETCH_USER:    ?1
HTTP_SEC_FETCH_MODE:    navigate
HTTP_SEC_FETCH_SITE:    none
HTTP_ACCEPT:    text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
HTTP_USER_AGENT:    Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.50
HTTP_UPGRADE_INSECURE_REQUESTS: 1
HTTP_SEC_CH_UA_PLATFORM:    "Windows"
HTTP_SEC_CH_UA_MOBILE:  ?0
HTTP_SEC_CH_UA: " Not A;Brand";v="99", "Chromium";v="98", "Microsoft Edge";v="98"
HTTP_CONNECTION:    close
HTTP_HOST:  www.example.com
HTTP_AUTHORIZATION: 
BACKEND_NAME:   httpd1
HOSTNAME:   lucy.onebit.cz
HTTPS:  on
force_response_1_0: 1
downgrade_1_0:  1
ssl_unclean_shutdown:   1
nokeepalive:    1
Front_End_Https:    on
UNIQUE_ID:  Yg_L4xNbf-I51ics4Sn1UQAAAdM
REDIRECT_STATUS:    200
REDIRECT_BACKEND_NAME:  httpd1
REDIRECT_HOSTNAME:  lucy.onebit.cz
REDIRECT_HTTPS: on
REDIRECT_force_response_1_0:    1
REDIRECT_downgrade_1_0: 1
REDIRECT_ssl_unclean_shutdown:  1
REDIRECT_nokeepalive:   1
REDIRECT_Front_End_Https:   on
REDIRECT_UNIQUE_ID: Yg_L4xNbf-I51ics4Sn1UQAAAdM
PHP_SELF:   /test2.php
REQUEST_TIME_FLOAT: 1645202403.7653
REQUEST_TIME:   1645202403
HTTP_FRONT_END_HTTPS:   on
URL:    /test2.php
STATUS: 200

But I think, the problem is with Mod rewrite disabled.

如果禁用了 mod_rewrite(并且启用了 .htaccess 覆盖),那么您将收到 500 内部服务器错误,而不是重定向循环。

如果另一个服务正在管理与客户端的 SSL 连接(例如 front-end 代理、负载平衡器、CDN 等)并且您的应用程序服务器通过不安全的 HTTP 连接,您将得到一个重定向循环到这个其他服务。 (并不少见。)

检查到达您的应用程序服务器的 HTTP 请求 header,您看到 X-Forwarded-Proto header 了吗?这表明应用程序服务器位于管理 SSL 连接的 front-end 代理之后。在这种情况下,您可以改为执行以下操作:

RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

注意:首先使用 302(临时)重定向进行测试以避免潜在的缓存问题。

测试前您需要清除浏览器缓存。

不过,这也可以是 host-specific。 一些 共享主机设置了一个 HTTPS environment 变量(不要与 HTTPS Apache server 变量,如第一个示例中所用),因此您也可以尝试以下操作:

RewriteCond %{ENV:HTTPS} =off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

更新: 根据 PHP $_SERVER 超全局的输出,尝试以下操作:

RewriteCond %{ENV:HTTPS} !on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

这背后的原因...当通过 HTTP 请求时根本没有 HTTPS 数组索引,当通过 HTTPS 请求时它被设置为 on。这必须是一个环境变量(由主机设置),而不是 Apache server 变量,因为始终会设置服务器变量。

旁白:上述规则中的两个条件(即%{HTTP:X-Forwarded-Proto} =http%{ENV:HTTPS} =off)将简单地失败(因为这些都没有设置)并且规则什么都不做。

注意:您必须首先使用 302(临时)重定向进行测试,并确保浏览器缓存在测试之前是清晰的。