使用 Tomcat 在后端使用 HTTP 的 ELB Https,无需 nginx 或 haproxy

使用 Tomcat 在后端使用 HTTP 的 ELB Https,无需 nginx 或 haproxy

我想设置 ELB 以在负载均衡器上终止 SSL 并通过 HTTP 与后端实例通信。我已在 ELB 上上传了有效证书。当我设置以下配置时

ELB-HTTPS

后端-HTTP

然后,如果应用程序在应用程序中执行重定向,客户端/浏览器将重定向到 HTTP 而不是 HTTPS。

但是,如果我将 ELB 设置为使用 HTTPS,并且后端实例也使用 HTTPS(甚至使用自签名证书),那么一切都可以正常工作,因为两种配置都在 HTTPS 上!

我在用雄猫在后端实例上,并且不想在其间使用任何其他层(例如 nginx 或 haproxy)

答案1

我发现这篇文章看起来与您的问题非常相似:http://willwarren.com/2014/01/27/running-apache-tomcat-with-ssl-behind-amazon-elb/

基本上说明了将 server.xml 更改为以下内容:

<Connector
    port="8080"
    protocol="HTTP/1.1"
    proxyPort="443"
    scheme="https"
    secure="true"
    proxyName="myapp.example.com"
    connectionTimeout="20000"
    URIEncoding="UTF-8"
    redirectPort="8443" />

答案2

我花了好长时间在网上寻找这个,最后我找到了一种方法来做到这一点。

问题是,一旦 http 在 ELB 内部重定向到 https 端口,它就会被重定向回端口 80,从而形成循环。发生这种情况的原因是 ELB 卸载 SSL,然后再次连接到端口 80。

最后经过一番研究,我得到了正确的重写规则来管理 X-Forwarded-Proto,这样即使 ELB 卸载了 SSL,tomcat 现在也可以使用 SSL 来处理原始请求。

这是使用 Tomcat 8 上的 Tomcat Valves 完成的。我相信在早期版本上也可以做到这一点。我已使用 Valves 在 Tomcat 上启用了重写规则。之后,它就像在 Apache 上编写重定向规则一样简单。

步骤如下:

步骤1: a. 打开 tomcat conf 文件夹下的 context.xml b. 将以下行粘贴到下面

<Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />

注意:这将全局启用阀门。如果需要为特定主机启用此功能,则应将其粘贴到该特定域的 server.xml 中

第2步:

</Host>a. 打开 conf/server.xml b. 将以下行粘贴到标签上方

<Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />

步骤3:

a. 打开 web.xml 所在的文件夹。例如,如果应用程序托管在 ROOT 下,则 web.xml 将位于 webapps/ROOT/WEB-INF 下

b. 类似地,如果应用程序托管在 webapps/myappfolder 下,则 web.xml 将位于 webapps/myappfolder/WEB-INF 下

c. 在 WEB-INF 文件夹中创建新文件rewrite.config.并粘贴以下重写规则:

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

答案3

Ravi 的答案中的 rewrite.config 规则对我不起作用。使用 Tomcat 8.0.32、AWS ELB 和 EC2,我的规则是:

# bounce all requests coming in on HTTP to HTTPS
RewriteCond %{HTTP:X-Forwarded-Proto} ^http$
RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]

顺便说一句:请记住,带有 301 的 HTTP 重定向会缓存在浏览器中,如果它成功一次,那么除非您删除浏览器缓存的重定向,否则您将无法再次看到它成功

答案4

这可能是一个老问题,但很难找到答案。这里有两个问题 1. Tomcat Web 容器正在接收 http 上的请求,因此它将构建的重定向将位于同一位置。Spring 可以在一定程度上提供帮助,但还不够。2. 即使用户试图访问 HTTP,也会将用户重定向到 HTTPS

第二个问题比较简单,因为 ELB 在标头中发送此信息。可以通过在现有过滤器或新过滤器中添加简单代码来解决

String protocol =req.getHeader("X-Forwarded-Proto");
    if(protocol!=null && "http".equalsIgnoreCase(protocol)){
        rep.sendRedirect( req.getRequestURL().toString().replaceFirst("http", "https"));
        return;
    }

对于第一个问题,对我有用的解决方案之一是在 spring servlet 的视图解析器中添加附加属性(redirectHttp10Compatible)。

<bean id="tilesviewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">

    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView" />
    <property name="redirectHttp10Compatible" value="false" />
 </bean>

如果 Spring 只解决重定向问题,那么一切就都好了,但由于问题出在容器本身,因此需要更多帮助。最终的解决方案是操作 server.xml 并为 tomcat 引擎添加 RemoteIpValve 属性 RemoteIpValve 的 JavaDoc

这是最后的修复。希望有帮助。

相关内容