SSL在Heroku中重定向 [英] SSL redirects in Heroku

查看:119
本文介绍了SSL在Heroku中重定向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



这是我的:



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

 < security-constraint> 
< web-resource-collection>
< web-resource-name> SSL网址< / 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(使用Heroku部署插件用于Atlassian Bamboo)和应用程序启动后,我最终在浏览器中出现了重定向错误 - 看起来它与https和http之间的轻弹有关,但我无法弄清楚我需要做些什么来修复它。



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

解决方案

我通过在我的Spring Security配置中使用 requires-channel 和Tomcat的 RemoteIpValve 。如果你没有使用Spring Security,配置 RemoteIpValve 应该足够了(以下假设你使用了优秀的 webapp-runner 作为你的容器)我想有一个jetty runner的等价物,但我不知道它...



问题是Heroku的web / routing层处理SSL,并将请求作为普通的HTTP代理到您的web应用程序。因此,Tomcat不知道该请求是否安全在其他地方(SSL卸载) RemoteIpValve 本质上覆盖了Tomcat看到的协议,端口和IP地址(并且反过来又是如何通过查看由处理SSL的代理服务器设置的HTTP头, request.isSecure()被评估)。

使用以下内容创建 context.xml

 < Context> ; 
< Valve className =org.apache.catalina.valves.RemoteIpValveremoteIpHeader =x-forwarded-forprotocolHeader =x -forwarded-protoportHeader =x -forwarded-port/>
< / Context>

这三个标题( x-forwarded-for x-forwarded-proto x -forwarded-port )由Heroku的路由层自动发送。 / p>

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

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

最后,确保webapp-runner指向context.xml(例如,使用webapp-runner 7.0 .30.1,它支持 context-xml 参数)。在您的 Procfile 中:

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

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



希望这对你有用...


I'm having loads of trouble getting my Java web app working on Heroku.

This is what I have:

A Java web app (standard war file) using Spring Security with a security-constraint section in my web.xml that looks like this:

    <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> 

When I deploy my WAR file to Heroku (using the Heroku deploy plugin for Atlassian Bamboo) and the app starts up, I end up getting a 'too many redirects' error in my browser - it looks like it has something to do with flicking between https and http but I can't figure out what I need to do to fix it.

I just want to use the piggyback SSL for now, as the SSL add-on is quite pricey for my hobby project (at $20 a month).

解决方案

I solved a similar problem by using a combination of requires-channel in my Spring Security configuration and Tomcat's RemoteIpValve. If you are not using Spring Security, configuring RemoteIpValve should be sufficient (the following assumes you are using the excellent webapp-runner as your container) I imagine there is an equivalent for jetty-runner, but I don't know it...

The issue is that Heroku's web/routing tier handles the SSL, and proxies the request to your webapp as plain HTTP. So Tomcat doesn't know the request is secured elsewhere (SSL offloading) RemoteIpValve essentially over-rides the protocol, port and IP address that Tomcat sees (and, in turn, how request.isSecure() is evaluated) by looking at HTTP headers set by the proxying server that handled the SSL.

Create a context.xml with the following:

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

Those three headers (x-forwarded-for, x-forwarded-proto, and x-forwarded-port) are automatically sent by Heroku's routing tier.

Next, ensure that the file gets copied somewhere in your maven target dir (I put it in the same dir as webapp-runner itself). In 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>

Finally, make sure webapp-runner points to the context.xml (e.g., using webapp-runner 7.0.30.1, which supports the context-xml argument). In your Procfile:

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

As a final note, I use of Spring Security requires-channel on <sec:intercept-url> to toggle back and forth between HTTP and HTTPS by flipping an environment variable - unset on my local dev box for easy configuration, set on Heroku (via heroku config) to selectively force SSL in different environments.

Hope this works for you...

这篇关于SSL在Heroku中重定向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆