2

我在让我的 Java Web 应用程序在 Heroku 上运行时遇到了很多麻烦。

这就是我所拥有的:

一个使用 Spring Security 的 Java Web 应用程序(标准 War 文件),在我的 web.xml 中有一个安全约束部分,如下所示:

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>SSL URLs</web-resource-name>
            <url-pattern>/j_spring_security_check</url-pattern>
            <url-pattern>/secure/account/create</url-pattern>
            <url-pattern>/register</url-pattern>
            <url-pattern>/login/*</url-pattern>
            <url-pattern>/</url-pattern> 
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint> 

当我将 WAR 文件部署到 Heroku(使用 Atlassian Bamboo 的 Heroku 部署插件)并且应用程序启动时,我最终在浏览器中收到“重定向过多”错误 - 看起来它与在https 和 http 但我不知道我需要做什么来修复它。

我现在只想使用搭载 SSL,因为 SSL 插件对于我的爱好项目来说非常昂贵(每月 20 美元)。

4

3 回答 3

12

我通过结合使用requires-channelSpring Security 配置和 Tomcat 的RemoteIpValve. 如果您不使用 Spring Security,配置RemoteIpValve应该就足够了(以下假设您使用的是优秀webapp-runner的容器)我想 jetty-runner 有一个等价物,但我不知道......

问题是 Heroku 的 web/路由层处理 SSL,并将请求作为纯 HTTP 代理到您的 webapp。因此,Tomcat 不知道请求在其他地方受到保护(SSL 卸载)本质上会通过查看代理服务器设置的 HTTP 标RemoteIpValve头来覆盖 Tomcat 看到的协议、端口和 IP 地址(以及如何评估)request.isSecure()处理了 SSL。

使用以下内容创建一个context.xml

<Context>
  <Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="x-forwarded-for" protocolHeader="x-forwarded-proto" portHeader="x-forwarded-port"/>
</Context>

这三个标头(x-forwarded-forx-forwarded-protox-forwarded-port)由 Heroku 的路由层自动发送。

接下来,确保将文件复制到您的 maven 目标目录中的某个位置(我将其放在与webapp-runner自身相同的目录中)。在pom.xml

<resources>
  <resource>
    <directory>${basedir}/src/main/resources/META-INF</directory>
    <includes>
      <include>context.xml</include>
    </includes>
    <targetPath>${project.build.directory}/dependency</targetPath>
  </resource>
</resources>

最后,确保 webapp-runner 指向 context.xml(例如,使用支持context-xml参数的 webapp-runner 7.0.30.1)。在你的Procfile

web: java $JAVA_OPTS -jar target/dependency/webapp-runner.jar --context-xml target/dependency/context.xml ...etc...

最后一点,我使用 Spring Security requires-channelon<sec:intercept-url>通过翻转环境变量在 HTTP 和 HTTPS 之间来回切换 - 在我的本地开发框上取消设置以便于配置,在 Heroku 上设置(通过heroku config)有选择地在不同环境中强制 SSL。

希望这对你有用...

于 2012-11-30T17:20:02.137 回答
3

我在使用webapp-runner时遇到了完全相同的问题,并通过简单地使用来修复它,如此--proxy-base-url https://example.com所述

于 2017-04-18T16:33:21.867 回答
1

@bimsapi 提供的解决方案对我有用。我使用这个解决方案遇到了两个问题。一旦我解决了这些问题,它就会完美运行。

首先,我必须将 context.xml 文件直接放在 war 文件的根目录下的 META-INF 目录中。

其次,您提供给 --context-xml 属性的 context.xml 文件的路径是文件系统上根目录的相对路径,而不是 war 文件。如--context.xml ./tartget/myapp/META-INF/context.xml。

在我给出 --context.xml META-INF/context.xml 之前这是错误的。

于 2017-07-21T01:59:34.690 回答