Options -Indexes
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_USER_AGENT} ^(.+)$
RewriteCond %{SERVER_NAME} ^example\.com$
RewriteRule .* https://www.%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
Header add Strict-Transport-Security "max-age=300"
</IfModule>
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header always set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
这里有许多问题会阻碍HSTS正常工作,并且应该进行一些额外的优化。
-
您没有重定向
http://www.example.com
(即www子域)转换为HTTPS。您需要将HTTP+WWW重定向到HTTPS+WWW才能兼容HSTS。
-
您正在重定向
http://example.com/
(即HTTP+non-www)到HTTPS+www。为了符合HSTS,您需要重定向到
同一主机
第一即。
http://example.com/
到
https://example.com/
到
https://www.example.com
(是的,这是两个重定向,但这种情况也很少见,每个用户代理最多只发生一次,因为返回的是STS头)。
-
你的指令顺序不对。您的规范重定向(即HTTP到HTTPS和非www到www)需要
之前
您的前控制器重写(第一条规则)。通过将它们放在前控制器之后,除了主页、目录和静态资源之外,它们永远不会被处理。如。
http://example.com/<some-url>
将永远不会被写入的规则重定向。不确定您是如何测试HSTS与SEMrush的合规性的,但与当时编写的指令一致
http://example.com/<一些url>
会失败,因为它没有重定向。
-
你应该删除第一个
Header
指令-这与第二个直接冲突(正确)
头球
指令。这个
always
条件(在第二个实例中使用)是必需的,以便将标头设置为
HTTPS 301将非www重定向(即非2xx响应)到www。
-
您应该包括
includeSubDomains
关于的指令
Strict-Transport-Security
以便在请求域顶点时覆盖www子域。虽然
全部的
子域现在将被隐式地包括在内。如果没有这一点,将需要显式地请求www子域。(好的,在下一个请求中,您将重定向到www。)
-
您应该删除
<IfModule>
包装物;它们不是必需的。这些指令是强制性的,不是
可选择的
(这些包装的存在暗示了这一点)。如果mod_rewrite不可用,您的网站可能会失败,并且您将不符合HSTS。
看见
my answer
到Webmasters堆栈上的以下问题,了解有关此方面的更多信息:
Is Checking for mod_rewrite Really Necessary?
-
我从前面的HTTP+non-www重定向中假设,您不在管理SSL的前端代理(或负载均衡器)后面,在这种情况下,检查
%{HTTP:X-Forwarded-Proto}
在后面
<If>
应删除表达式。如果您不是“代理”的幕后主使,则可以伪造请求以防止
STS
正在发送回的标头(用户应该无法执行此操作)。
相反,如果您在“代理”后面,则检查
%{REQUEST_SCHEME} == 'https'
是多余的,但不会造成伤害。顺便说一句,的使用
REQUEST_SCHEME
假设您使用的是Apache 2.4+(我希望您使用的),但是,如果您仍使用Apache 2.2,则此检查将失败,并且不会设置STS标头。
因此,考虑到以上几点
.htaccess
文件应该这样写:
Options +FollowSymLinks -Indexes
RewriteEngine On
# Redirect HTTP to HTTPS on the same host (requirement of HSTS)
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Redirect non-www to www (HTTPS only)
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Front-controller
RewriteRule ^index\.php/ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php/$1 [L]
<If "%{REQUEST_SCHEME} == 'https'>
# The "always" condition is required to set the header on the HTTPS redirect
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</If>
附加说明:
-
我用过
HTTP_HOST
而不是
SERVER_NAME
自从你
需要
请求中存在的主机名。默认情况下
服务器名称
与相同
HTTP_HOST
,但这可能因服务器配置而异。
-
当请求中存在非空的用户代理字符串(恶意请求可能会抑制用户代理字符串)时,没有理由像最初那样只应用规范重定向,所以我已经删除了这个条件。如果有什么不同的话,你会阻止这样的请求。
-
正则表达式
^
在中
RewriteRule
图案
比
.*
因为它只需要成功——实际上不需要
火柴
任何东西,因为它以后不会被使用。
-
额外的
RewriteRule ^index\.php/ - [L]
“前端控制器”之前的指令只是一种优化,以防止重写的URL不必要地通过随后的文件系统检查。
参考/另请参阅:
更新:
请尝试以下操作。由于您在AWS上,您可能需要检查
X-Forwarded-Proto
HTTP请求标头而不是
HTTPS
Apache服务器变量,以确定对客户端的请求是否安全。
所需的更改是对HTTP到HTTPS重定向(第一条规则)和
<如果>
最后的表达式。
Options +FollowSymLinks -Indexes
RewriteEngine On
# Redirect HTTP to HTTPS on the same host (requirement of HSTS)
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Redirect non-www to www (HTTPS only)
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Front-controller
RewriteRule ^index\.php/ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php/$1 [L]
<If "%{HTTP:X-Forwarded-Proto} == 'https'>
# The "always" condition is required to set the header on the HTTPS redirect
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</If>