2012-11-15 62 views
2

我在加載Heroku中的Java Web應用程序時遇到了很多麻煩。Heroku中的SSL重定向

這是我有:

一個Java Web應用程序中使用Spring安全,在我的web.xml中的安全性約束部分,看起來像這樣(標準war文件):

<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(使用Heroku部署插件用於Atlassian Bamboo)並啓動應用程序,結果在我的瀏覽器中出現了「太多重定向」錯誤 - 它看起來像是在https之間輕彈一下和http,但我無法弄清楚我需要做些什麼來解決它。

我現在只想使用搭載SSL,因爲SSL附加組件對於我的愛好項目(每月20美元)非常昂貴。

+0

這可能是由於Heroku如何總是嚮應用程序發送http(不是https)。我有一個示例應用程序以不同的方式處理這個問題:https://github.com/jamesward/springmvc-https-enforcer不知道這是否有幫助。 –

+0

嗯,所以它不是全部或沒有SSL呢? – JMM

+0

不需要。但是您可能需要在Heroku上做一些額外的工作才能正確確定請求是否最初是https。你將不得不使用'x -forwarded-proto'請求頭。這可能有所幫助:http://stackoverflow.com/questions/5741210/handling-x-forwarded-proto-in-java-apache-tomcat –

回答

10

我通過在我的Spring Security配置中使用requires-channel和Tomcat的RemoteIpValve組合解決了類似的問題。如果你沒有使用Spring Security,配置RemoteIpValve應該足夠了(以下假設你使用優秀的webapp-runner作爲你的容器)我想有一個等同於jetty-runner,但我不知道它...

問題是Heroku的Web /路由層處理SSL,並將請求作爲普通的HTTP代理到您的webapp。因此,Tomcat不知道該請求是否安全在其他地方(SSL卸載)RemoteIpValve通過查看由代理設置的HTTP標頭實質上覆蓋了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> 

最後,確保web應用澆道指向context.xml中(例如,使用web應用澆道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>使用Spring Security requires-channel通過翻轉一個環境變量來來回切換HTTP和HTTPS之間 - 在易於配置我的本地開發框未設置,設置在Heroku上(通過heroku config)在不同環境中選擇性強制使用SSL。

希望這對你的作品...

+0

謝謝,你是一個救生員,我會花幾個小時弄清楚這一點。我遇到的唯一問題是:我不得不重新添加到我的mvn項目的默認資源文件夾中。新的資源指令覆蓋了我用來自動工作的默認資源文件夾。謝謝! src/main/resources \

+0

聽起來不錯。你是否也可能得到了「NoSuchBeanDefinitionException:在啓動時沒有定義名爲'springSecurityFilterChain'的bean?只要我在pom.xml中添加就可以得到它。我甚至在指定--context-xml標誌之前得到它。有任何想法嗎? –

+0

拯救生命。非常感謝。 – Junjie

0

我面臨使用的webapp亞軍完全相同的問題,並通過簡單地使用--proxy-base-url https://example.com固定它,描述here

0

該解決方案通過提供@ 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之前,這是錯誤的。