如何使用Spring Boot和Tomcat指定我的.keystore文件?

时间:2013-10-27 00:57:55

标签: spring tomcat spring-boot

我正在尝试设置Spring Security以使用Spring Boot的嵌入式Tomcat实例。有相当多的基本样本可以做到这一点,但我被困在他们离开的地方 - 他们通过HTTP(而不是HTTPS)进行基本身份验证。

如果我可以访问Tomcat配置文件(server.xml),我可能会工作但是由于Spring Boot使用嵌入式Tomcat实例(这是一个非常方便),我无法访问Tomcat配置文件(至少,据我所知)。

可能有application.properties设置,但我无法追踪它。我已经看到server.contextPathapplication.properties字段的引用,我怀疑它可能与替换Tomcat配置文件有关。即使它是相关的,我也不知道从哪里开始 - 我见过的所有Tomcat SSL指令都是从编辑现有的server.xml文件开始的,而不是从头开始构建一个。

这可以通过Spring Boot完成(通过某种方式指定server.xml的片段或通过其他方式)?如果没有,最简单的方法是什么?我知道我可能需要排除Spring Boot的Tomcat组件,但如果可能的话,我宁愿避免使用它。

5 个答案:

答案 0 :(得分:55)

从Spring Boot 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的链接。

答案 1 :(得分:18)

事实证明有一种方法可以做到这一点,虽然我不确定我是否找到了'正确'的方式,因为这需要几个小时从多个项目中读取源代码。换句话说,这可能是很多愚蠢的工作(但它确实有效)。

首先,无法获取嵌入式Tomcat中的server.xml,无论是扩充还是替换它。这必须以编程方式完成。

其次,'require_https'设置无效,因为您无法以这种方式设置证书信息。 设置从http到https的转发,但它没有为您提供使https工作的方法,因此转发不会有用。但是,请将其与下面的内容一起使用, 使https正常工作。

首先,您需要按照Embedded Servlet Container Support docs中的说明提供EmbeddedServletContainerFactory。这些文档适用于Java,但Groovy看起来几乎相同。请注意,我无法识别其示例中使用的@Value注释,但不需要它。对于groovy,只需将其放入一个新的.groovy文件中,并在启动spring启动时在命令行中包含该文件。

现在,说明说您可以自定义在该代码中创建的TomcatEmbeddedServletContainerFactory类,以便您可以更改web.xml行为,这是正确的,但对于我们的目的,知道您的重要性也可以用它来定制server.xml行为。实际上,阅读该类的源代码并将其与嵌入式Tomcat文档进行比较,您会发现这是唯一可以做到这一点的地方。有趣的函数是TomcatEmbeddedServletContainerFactory.addConnectorCustomizers(),它可能看起来不像Javadocs,但实际上为您提供了嵌入式Tomcat对象来自定义。只需传递您自己的TomcatConnectorCustomizer实现,并在Connector函数中的给定void customize(Connector con)上设置您想要的内容。现在,您可以使用Connector完成大约十亿件事情,但我找不到有用的文档,但此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;
}
}

Autowiring将使用它来运行此实现。一旦我修复了我的破坏的密钥库文件(确保你用-storetype pkcs12调用keytool,而不是在其他地方报告的-storepass pkcs12),这就行了。另外,提供参数(端口,密码等)作为测试的配置设置会更好......如果你能得到@Value注释来使用Groovy,我肯定是可能的。

答案 2 :(得分:9)

对于外部密钥库,前缀为"文件:"

app.run(host = 'your global ip from whatismyip', port = '5000')

答案 3 :(得分:0)

如果您不想实施connector customizer,则可以构建并导入提供预定义connector customizer的库(https://github.com/ycavatars/spring-boot-https-kit)。根据自述文件,您只需创建密钥库,配置connector.https.*,导入库并添加@ComponentScan("org.ycavatars.sboot.kit")。然后,您将拥有HTTPS连接。

答案 4 :(得分:-1)