在Heroku上使用Embedded Jetty强制执行HTTPS

时间:2012-07-19 15:53:31

标签: heroku https jetty

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

应用程序识别通过https发出的请求,但它也接受http请求而不重定向(它不应该这样做)。此外,如果用户以https连接启动,则只要发布表单并将其重定向到“GET”请求,任何https连接都将恢复为http。

我尝试添加一个只是将“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>

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

我确信这个问题已得到解决,但我无法为我的生活找到我需要做的工作才能完成这项工作。

BTW,我也尝试将以下内容添加到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>

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:3)

您需要检查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);

答案 1 :(得分:0)

我已经检查过Heroku(也许我在这里想念一个版本,还有buildpack等等)但是你肯定没有这些信息:

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