2013-10-27 58 views
32

我試圖設置Spring Security來與Spring Boot的嵌入式Tomcat實例一起工作。有相當多的基本樣本可以做到這一點,但是我堅持在他們離開的地方 - 他們通過HTTP(而不是HTTPS)進行基本身份驗證。如何使用Spring Boot和Tomcat指定我的.keystore文件?

如果我有權訪問Tomcat配置文件(server.xml),但是由於Spring Boot使用嵌入式Tomcat實例(這非常方便),我可能會使其工作,但我沒有訪問Tomcat配置文件(至少,不是我所知)。

可能有一個application.properties設置爲此,但我一直無法追查它。我見過參考application.properties中的server.contextPath字段,我懷疑可能與更換Tomcat配置文件有關。即使它是相關的,我也不知道從哪裏開始 - 我見過的所有Tomcat SSL指令都是從編輯現有的server.xml文件開始,而不是從頭開始構建。

這可以通過Spring Boot來完成(通過某種方式指定server.xml的片段或通過其他方式)?如果不是,那麼最簡單的方法是什麼?我知道我可能需要排除Spring Boot的Tomcat組件,但如果可能,我寧願避免這種情況。

+1

我發現,使用不同的'application.properties'設置,'server.tomcat.basedir',這讓我覺得作爲另一個例子更可能與嵌入式Tomcat配置有關。我無法做任何事情,但它可能更接近正確的方向,並可能使我的問題更清晰。 – Dave

+1

沒有運氣的命令行環境變量: '-Djavax.net.ssl.keyStore =/path/to/keystore'' -Djavax.net.ssl.keyStorePassword = keyStorePass' 要麼。 – Dave

回答

17

事實證明,有一種方法可以做到這一點,雖然我不知道我找到了「正確」的方法,因爲這需要幾個小時的閱讀來自多個項目的源代碼。換句話說,這可能是很多愚蠢的工作(但它的工作原理)。

首先,無法獲取嵌入式Tomcat中的server.xml,無論是擴充還是替換它。這必須以編程方式完成。

其次,'require_https'設置沒有幫助,因爲您無法以這種方式設置證書信息。它確實設置從http轉發到https,但它沒有給你一個方法使https工作,因此轉發沒有什麼幫助。但是,使用它與下面的東西,其中使https工作。

首先,您需要提供EmbeddedServletContainerFactory,如Embedded Servlet Container Support docs中所述。該文檔適用於Java,但Groovy看起來幾乎相同。請注意,我無法識別其示例中使用的@Value註釋,但不需要它。對於groovy,只需將其放在一個新的.groovy文件中,並在啓動spring引導時將該文件包含在命令行中。

現在,說明聲明您可以自定義在該代碼中創建的TomcatEmbeddedServletContainerFactory類,以便您可以改變web.xml的行爲,這是真的,但對於我們的目的而言,知道您也可以使用它來定製server.xml行爲。事實上,閱讀該課程的源代碼並將其與Embedded Tomcat文檔進行比較,您會發現這是唯一能做到這一點的地方。有趣的功能是TomcatEmbeddedServletContainerFactory.addConnectorCustomizers(),它可能不像Javadocs那麼多,但實際上爲您提供了嵌入式Tomcat對象來自定義自己。只需傳遞您自己的TomcatConnectorCustomizer實現,並在函數中將給定Connector上的所需內容設置爲void customize(Connector con)函數。現在,您可以使用Connector執行大約10億次的操作,但我找不到有用的文檔,但this guys personal Spring-embedded-Tomcat project中的createConnector()函數是非常實用的指南。我的實現最終看起來是這樣的:

package com.deepdownstudios.server 

import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer 
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory 
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory 
import org.apache.catalina.connector.Connector; 
import org.apache.coyote.http11.Http11NioProtocol; 
import org.springframework.boot.* 
import org.springframework.stereotype.* 

@Configuration 
class MyConfiguration { 

@Bean 
public EmbeddedServletContainerFactory servletContainer() { 
final int port = 8443; 
final String keystoreFile = "/path/to/keystore" 
final String keystorePass = "keystore-password" 
final String keystoreType = "pkcs12" 
final String keystoreProvider = "SunJSSE" 
final String keystoreAlias = "tomcat" 

TomcatEmbeddedServletContainerFactory factory = 
     new TomcatEmbeddedServletContainerFactory(this.port); 
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { 
    void customize(Connector con) { 
     Http11NioProtocol proto = (Http11NioProtocol) con.getProtocolHandler(); 
      proto.setSSLEnabled(true); 
     con.setScheme("https"); 
     con.setSecure(true); 
     proto.setKeystoreFile(keystoreFile); 
     proto.setKeystorePass(keystorePass); 
     proto.setKeystoreType(keystoreType); 
     proto.setProperty("keystoreProvider", keystoreProvider); 
     proto.setKeyAlias(keystoreAlias); 
    } 
}); 
return factory; 
} 
} 

自動裝配將選擇這個實現與它一起運行。一旦我修復了我的破解密鑰庫文件(確保你使用-storetype pkcs12而不是-storepass pkcs12調用keytool,如其他地方報告),這工作。另外,將參數(端口,密碼等)作爲測試配置設置等等會更好。如果您可以使用@Value註釋來與Groovy一起工作,我相信它是可能的。

+2

感謝您查看所有這些,我一直在考慮在spring-boot中的https支持。也許這是一個春季啓動的限制,需要一個錯誤報告? HTTPS是任何Web應用程序的基本要求,奇怪的是它沒有更好的文檔記錄和更好的支持。 – Jay

+2

現在在spring引導文檔中有記錄:https://github.com/spring-projects/spring-boot/blob/master/docs/howto.md – Jay

+0

通過application.yml提供這些SSL屬性有何區別並有我們自己的TomcatConnectorCustomizer實現? – yathirigan

0

如果您不想執行您的connector customizer,則可以構建並導入提供預定義的connector customizer的庫(https://github.com/ycavatars/spring-boot-https-kit)。根據自述文件,您只需創建密鑰庫,配置connector.https.*,導入庫並添加@ComponentScan("org.ycavatars.sboot.kit")。然後你會有HTTPS連接。

41

與Spring 1.2啓動開始,您可以使用application.propertiesapplication.yml配置SSL。下面是application.properties一個例子:

server.port = 8443 
server.ssl.key-store = classpath:keystore.jks 
server.ssl.key-store-password = secret 
server.ssl.key-password = another-secret 

同樣的事情application.yml

server: 
    port: 8443 
    ssl: 
    key-store: classpath:keystore.jks 
    key-store-password: secret 
    key-password: another-secret 

這裏給current reference documentation的鏈接。

+3

確實有效。 Spring Boot非常棒! – Maksim

+2

通過application.yml提供這些SSL屬性和自己實現TomcatConnectorCustomizer(如下面的答案)之間有什麼區別? – yathirigan

+4

簡單性vs控制。 –

2

對於外部密鑰庫,前綴「文件:」

server.ssl.key-store=file:config/keystore 
相關問題