此答案假定您已在负载均衡器安全组中启用 https,将 SSL 证书添加到负载均衡器,负载均衡器转发端口 80 和 443,并将您的域名指向具有 Route 53 的 Elastic Beanstalk 环境(或等效的 DNS 服务)。
选项 1:使用 Apache 进行重定向
仅当您位于使用 Apache 的 Elastic Beanstalk 环境中时,这才有可能(可以将基于 AWS Linux 2 的部署配置为使用 Apache)。它可能不适用于基于 docker 的部署。
亚马逊 Linux 2
大多数基于 AWS Linux 版本 2 的平台都可以选择 Apache 作为您的代理主机。这可以通过转到“配置”>“软件”>“容器选项”并将“代理服务器”设置为“Apache”来完成,或者将以下内容添加到您的.config
文件之一.ebextensions
:
option_settings:
aws:elasticbeanstalk:environment:proxy:
ProxyServer: apache
完成后,添加一个名为.platform/httpd/conf.d/ssl_rewrite.conf
您的代码库(相关 AWS 文档)的配置文件,其中包含以下内容:
RewriteEngine On
<If "-n '%{HTTP:X-Forwarded-Proto}' && %{HTTP:X-Forwarded-Proto} != 'https'">
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</If>
亚马逊 Linux 1
您需要做的就是将以下内容添加到项目目录中的一个.config
文件中.ebextensions
:
files:
"/etc/httpd/conf.d/ssl_rewrite.conf":
mode: "000644"
owner: root
group: root
content: |
RewriteEngine On
<If "-n '%{HTTP:X-Forwarded-Proto}' && %{HTTP:X-Forwarded-Proto} != 'https'">
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</If>
解释
这在 Elastic Beanstalk 之外是相当直接的。通常会添加一个 Apache 重写规则,如下所示:
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
或者,如果在负载均衡器后面,就像我们在这种情况下一样:
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
但是,这些配置仅在一个<VirtualHost>
块内起作用。将 更改RewriteCond
为<If>
块允许它在块之外正常工作<VirtualHost>
,允许我们放入独立的 Apache 配置文件中。请注意,CentOS 上的标准 Apache 设置(包括 ElasticBeanstalk 上的设置)包含所有/etc/httpd/conf.d/*.conf
匹配的文件,它与我们存储此文件的文件路径匹配。
如果您不在负载均衡器后面,则条件的-n '%{HTTP:X-Forwarded-Proto}'
一部分会阻止它重定向,从而允许您在具有负载均衡器和 https 的生产环境与单实例且没有 https 的暂存环境之间共享配置。如果您在所有环境中都使用负载均衡器和 https,则这不是必需的,但拥有它并没有什么坏处。
选项 2:使用 ALB 进行重定向
这仅在您使用 Application Load Balancer 时才有可能。亚马逊在此处提供了有关如何执行此操作的说明:https ://docs.aws.amazon.com/elasticbeanstalk/latest/dg/configuring-https-httpredirect.html
您需要做的就是将以下内容添加到项目目录中的一个.config
文件中,.ebextensions
以将 http 侦听器替换为重定向:
Resources:
AWSEBV2LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn:
Ref: AWSEBV2LoadBalancer
Port: 80
Protocol: HTTP
DefaultActions:
- Type: redirect
RedirectConfig:
Host: "#{host}"
Path: "/#{path}"
Port: "443"
Protocol: "HTTPS"
Query: "#{query}"
StatusCode: "HTTP_301"
我见过的糟糕的解决方案
我已经看到了很多关于这个问题的糟糕解决方案,值得通过它们来理解为什么这个解决方案是必要的。
使用 Cloudfront: 有人建议在 Elastic Beanstalk 前面使用非缓存 Cloudfront 设置来执行 HTTP 到 HTTPS 的重定向。这增加了一个不完全合适的全新服务(从而增加了复杂性)(Cloudfront 是一个 CDN;它不是在固有动态内容上强制使用 HTTPS 的正确工具)。Apache config 是这个问题的常规解决方案,而 Elastic Beanstalk 使用 Apache,所以我们应该这样做。
SSH 进入服务器并...:这与 Elastic Beanstalk 的观点完全相反,并且存在很多问题。通过自动缩放创建的任何新实例都不会具有修改后的配置。任何克隆的环境都没有配置。任何数量的合理环境更改都将清除配置。这真是个坏主意。
使用新文件覆盖 Apache 配置:这进入了正确的解决方案领域,但如果 Elastic Beanstalk 更改了服务器设置的各个方面(他们很可能会这样做),那么您将面临维护噩梦。另请参阅下一项中的问题。
动态编辑 Apache 配置文件以添加几行:这是一个不错的主意。这样做的问题是,如果 Elastic Beanstalk 更改其默认 Apache 配置文件的名称,它将无法正常工作,并且该文件可能会在您最不期望的时候被覆盖:https ://forums.aws.amazon.com/thread .jspa?threadID=163369