使用Spring Boot为X-FORWARDED-PROTO配置嵌入式Jetty 9

时间:2014-10-13 06:03:53

标签: spring amazon-web-services https jetty

我在AWS中运行Spring Boot应用程序。应用程序在Elastic Load Balancer(ELB)后面运行。 ELB配置为使用https(端口443)到外部世界,但通过http(端口8080)到应用程序。 ELB配置为通过x-forwarded-proto标头。我正在使用Jetty 9.0.0.M0和Spring Boot 1.1.5 RELEASE

我似乎收到了通过ELB从应用程序发回的不正确的重定向,其中重定向响应以http而不是https返回。现在,我读了here我应该设置"转发"标题为true使用:

<Set name="forwarded">true</Set>

我无法在Spring Boot中看到如何使用Jetty的嵌入式版本执行此操作,因为我的源代码中没有XML配置文件。

我查看了EmbeddedServletContainerCustomizer基础架构,但我仍然无法获得正确的咒语以使此设置正常工作。

应用程序是在AWS https环境之外构建和测试的,因此应用程序也需要透明地使用http。直接命中应用程序端点而无需通过ELB工作。只是ELB到申请路线不起作用。

有什么想法吗?

5 个答案:

答案 0 :(得分:6)

我自己有一个类似的问题,而研究时遇到了你的问题。我发现这很容易以编程方式进行,但在Jetty文档中并没有真正解释过。

Jetty xml配置文件的结构与java API的结构相匹配,因此您只需在代码中复制它。

遵循Jetty指南,了解如何使用XML配置文件here

进行配置

我能够以编程方式配置嵌入式服务器:

    Server server = new Server( port );

    // Create HTTP Config
    HttpConfiguration httpConfig = new HttpConfiguration();

    // Add support for X-Forwarded headers
    httpConfig.addCustomizer( new org.eclipse.jetty.server.ForwardedRequestCustomizer() );

    // Create the http connector
    HttpConnectionFactory connectionFactory = new HttpConnectionFactory( httpConfig );
    ServerConnector connector = new ServerConnector(server, connectionFactory);

    // Make sure you set the port on the connector, the port in the Server constructor is overridden by the new connector
    connector.setPort( port );

    // Add the connector to the server
    server.setConnectors( new ServerConnector[] { connector } );

答案 1 :(得分:0)

这里有一个刚刚为我们工作的Spring应用程序,它位于jetty-runner-9.3.6.jar之后。在我们的例子中,我们的jetty.xml已经没有任何addConnector,并且尝试仅添加addConnector会出错。

在此处找到它 - https://github.com/george-hawkins/authsite/blob/2c5d61b984a328ef878216a3acfd0ad2593f81b1/src/main/config/etc/jetty.xml

isCheapest

这样做是为了修改传递的Request对象,使其成为-look-就像它没有通过代理(用可用和支持的任何X-Forwarded标头替换细节)。 / p>

请参阅http://archive.eclipse.org/jetty/9.0.0.M4/apidocs/index.html?org/eclipse/jetty/server/ForwardedRequestCustomizer.html

此自定义程序查看标头的HTTP请求,表明它已由一个或多个代理转发。具体处理是:

  • X - 转发,主机
  • X - 转发,服务器
  • X - 转发,对于
  • X - 转发,原

如果存在这些标头,则会更新Request对象,以便代理不会被视为请求所在的连接的另一个端点

答案 2 :(得分:0)

我发现默认的Spring Boot Jetty配置存在一些问题,其中最重要的是启用了SSLLabs Check不喜欢的SSL算法。

无论如何:我找到的解决方案就是:

   @Bean
   public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() 
   {
      // Deploy the nuclear option, kill the default Spring Boot factory
      // and replace with mine that disables extra crud.
      JettyEmbeddedServletContainerFactory fac = new JettyEmbeddedServletContainerFactory();
      // This allows ELB to work.
      fac.setUseForwardHeaders( true );
      return fac;
   }

如果您希望SSL端到端,还需要设置许多其他ELB选项。我不得不使用命令行客户端进行一些调整并将运行状况检查更改为TCP:8443 b / c EC2实例证书对负载均衡器看起来无效。

答案 3 :(得分:0)

尝试在Spring Boot应用程序中设置以下属性:

onClick

这将确保从头读取正确的协议。请参阅此处的文档:

https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/html/howto-embedded-servlet-containers.html

答案 4 :(得分:-2)

我一直无法找到这个问题的简单Jetty 9解决方案。除了建议我升级到Jetty的更高版本(这是一个很好的建议),我没有收到任何其他建议(目前,你可以看到)

为了方便起见,我的解决方案是放弃Jetty,而是使用嵌入式tomcat,其中此功能在application.properties文件中只是一个简单的配置问题。只需将以下行添加到application.properties

server.tomcat.remote_ip_header=x-forwarded-for

这似乎是使用作为Spring Boot的一部分的默认嵌入式tomcat来实现的。