Apache 308 重定向将协议从 https 更改为 http

问题描述 投票:0回答:1

因此,我最近更新了 .htaccess,使用 308(而不是 Apache 通常使用的 301)复制目录斜杠指令,以便浏览器重复相同的请求,而不是将其更改为 GET 请求并从其他请求方法中删除数据。

# Disable 
DirectorySlash Off

# Recreate the DirectorySlash directive with 308
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ /$1/ [R=308,L]

这在我的本地测试中效果很好,但是当我使用使用 HTTPS 的测试服务器时,它突然崩溃了。 在 Chrome 开发工具中,我可以看到它被定向到不安全的 url 或某种原因。

错误:

Mixed Content: The page at 'https://...' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://...'. This request has been blocked; the content must be served over HTTPS.

我也尝试过像这样添加请求方案,但没有效果。

RewriteRule ^(.+[^/])$ %{REQUEST_SCHEME}://%{HTTP_HOST}/$1/ [R=308,L]

有谁知道为什么 Apache 将协议更改为不安全的协议吗?

更新: 我尝试检查协议并将其存储在变量中,因为 REQUEST_SCHEME 并不总是定义并导致它再次默认返回 http。

RewriteCond %{HTTPS} on
RewriteRule .* - [E=PROTO:https]
RewriteCond %{HTTPS} !on
RewriteRule .* - [E=PROTO:http]


RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ %{ENV:PROTO}://%{HTTP_HOST}/$1/ [R=308,L]

这最初似乎有效,但当请求是 POST 时,它仍然将 HTTPS 重定向到 HTTP。

更新:正如 arkascha 建议的那样,我尝试硬编码 HTTPS,这有效。

RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ https://%{HTTP_HOST}/$1/ [R=308,L]

这非常奇怪,因为变量方法应该产生相同的结果。初始请求是 HTTPS,因此变量最终应使用 HTTPS,就像硬编码方法一样。

所以我想我必须使用基于域的检查或其他一些解决方法,并复制 HTTP 与 HTTPS 的逻辑。

我觉得这对于让 308 重定向按照记录工作来说都是不必要的。

任何人都可以解释这种奇怪的行为吗?

apache .htaccess https http-status-code-308
1个回答
0
投票

我突然想到,如果

RewriteCond %{HTTPS} on
%{REQUEST_SCHEME}
的行为就像请求是 HTTP 一样,那么这意味着 Apache 一定会以某种方式接收 HTTP 请求,无论初始协议如何。

测试服务器由AWS托管,似乎HTTPS请求必须由AWS解密,然后以未加密的方式发送到Apache实例。 (我不知道这个服务器最初是如何设置的)。

解决方案是检查

X-Forarded-Proto
并设置要在重定向中使用的变量:

# Assume HTTP by default for local devs.
RewriteRule .* - [E=PROTO:http]
# Change to HTTPS if forwarded/current request is HTTPS.
RewriteCond %{HTTP:X-Forwarded-Proto} =https [OR]
RewriteCond %{HTTPS} on
RewriteRule .* - [E=PROTO:https]

# Recreate the DirectorySlash directive with 308
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ %{ENV:PROTO}://%{HTTP_HOST}/$1/ [R=308,L]

至于为什么这只是我的 POST 308 重定向,我唯一的理论是,当它是 GET 请求时,浏览器会默默地为我们更正协议,如果它不是 GET 请求,则更严格地遵循 308 指令。 否则,GET 请求应该也会出现同样的问题。

如果有人可以更详细地解释,特别是浏览器的行为(Chrome && Firefox),我很乐意接受另一个答案。

© www.soinside.com 2019 - 2024. All rights reserved.