【问题标题】:Enforce HTTPS with Embedded Jetty on Heroku在 Heroku 上使用嵌入式 Jetty 实施 HTTPS
【发布时间】:2012-07-19 15:53:30
【问题描述】:

我们有一个 Java servlet,使用嵌入式 Jetty 运行,使用“SSL Endpoint”插件部署到 Heroku。我要求应用程序中的所有页面都通过 HTTPS 提供,无论用户是使用 http 还是 https 导航到我们的应用程序。

应用程序识别通过 https 发出的请求,但它也接受 http 请求而不进行重定向(它不应该这样做)。此外,如果用户从 https 连接开始,那么每当发布表单并重定向到“GET”请求时,任何 https 连接都会恢复为 http。

我尝试添加一个 URL 过滤器,将“http://”简单地更改为“https://”,并使用以下代码进行重定向(为简洁起见删除了导入):

public class UrlFilter implements Filter
{
  protected FilterConfig filterConfig;

  @Override
  public void destroy(){}

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
  {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    String incomingUrl = httpRequest.getRequestURL().toString();
    if ( (!httpRequest.isSecure()) && incomingUrl.contains(".webapps.stjude.org")  )
    {
      String newUrl = incomingUrl.replace("http://", "https://");
      httpResponse.sendRedirect(newUrl);
    }
    chain.doFilter(request, response);
  }

  @Override
  public void init(FilterConfig filterConfig) throws ServletException
  {
    this.filterConfig = filterConfig;
  }
}

然后,我将其添加到我的 web.xml 文件中:

<filter>
  <filter-name>urlFilter</filter-name>
  <filter-class>org.stjude.radio.ui.filters.UrlFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>urlFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

这种方法的问题是应用返回“重定向过多”错误(重定向循环)。

我确信这个问题已经得到解决,但我无法终生找到我需要做些什么来完成这项工作。

顺便说一句,我也尝试将以下内容添加到 web.xml 中,但这只会导致请求失败。

<security-constraint>
  <web-resource-collection>
    <web-resource-name>SSL Pages</web-resource-name>
    <url-pattern>/*</url-pattern>
    <http-method>GET</http-method>
    <http-method>PUT</http-method>
    <http-method>POST</http-method>
  </web-resource-collection>
  <user-data-constraint>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
  </user-data-constraint>
</security-constraint>

任何帮助将不胜感激。

【问题讨论】:

  • 过滤器中使用的getRequestURL() 不包括原始 URL 的查询部分,因此在重定向时会丢失。还应该检查 getQueryString() 是否为非 null 并附加(带有前面的“?”)是这样的。

标签: heroku https jetty


【解决方案1】:

您需要检查x-forwarded-proto 标头以查看请求是否安全:

Boolean secure = false;
if (request.headers.get("x-forwarded-proto") != null) {
  secure = request.headers.get("x-forwarded-proto").values.contains("https");
}
System.out.println("secure = " + secure);

【讨论】:

  • James,这是 Heroku 特有的吗?
  • x-forwarded-proto 是负载均衡器的事实标准,它让后备服务器知道向负载均衡器发出请求的协议是什么。
  • 谢谢,詹姆斯。我试试看。
  • 好提示!这解决了我在 AWS Elastic Beanstalk 上遇到的问题。
  • Jetty 可以自动处理 x-forwarded 属性 - 这是通过 ForwardedRequestCustomizer 完成的(如 Jetty "configuring connectors" 文档页面中所述)。这避免了许多其他 x-forwarded 相关问题,例如在使用身份验证时,servlet 中的重定向总是重定向到 http 资源和问题。
【解决方案2】:

我已经与 Heroku 核对过(也许我在这里错过了一个版本,以及 buildpack 等等),但你肯定没有得到这些信息:

  • 一个 X-Forwarded-Proto 指向 http
  • 一个 HttpServletRequest#scheme 返回一个 http
  • 一个 HttpServletRequest#secure return false ....

【讨论】:

    猜你喜欢
    • 2016-12-16
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-25
    • 1970-01-01
    • 2017-09-03
    • 1970-01-01
    相关资源
    最近更新 更多