此答案假设您已在负载均衡器安全组中启用 https,将 SSL 证书添加到负载均衡器,负载均衡器转发端口 80 和 443,并将您的域名指向 Elastic Beanstalk 环境使用 Route 53(或等效的 DNS 服务)。
选项 1:使用 Apache 进行重定向
只有在使用 Apache 的 Elastic Beanstalk 环境中才有可能。它可能不适用于基于 docker 的部署。
亚马逊 Linux 2
大多数基于 AWS Linux 版本 2 的平台都可以选择 Apache 作为您的代理主机。这可以通过转到“配置”>“软件”>
“容器选项”并将“代理服务器”设置为“Apache”。
完成后,将名为 .platform/httpd/conf.d/ssl_rewrite.conf 的配置文件添加到您的代码库 (relevant AWS docs) 中,其内容如下:
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 files in the .ebextensions directory of your project 之一:
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 进行重定向
这只有在您使用应用程序负载均衡器时才有可能。亚马逊在这里有如何做到这一点的说明:https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/configuring-https-httpredirect.html
您需要做的就是将以下内容添加到您的.config files in the .ebextensions directory of your project 之一,以将 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