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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19613562/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 06:19:27  来源:igfitidea点击:

How can I specify my .keystore file with Spring Boot and Tomcat?

springtomcatspring-boot

提问by Dave

I'm trying to set up Spring Security to work with Spring Boot's embedded Tomcat instance. There are quite a few basic samples that do this but I'm stuck where they leave off -- they do basic authentication over HTTP (not HTTPS).

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

I could probably make it work if I had access to the Tomcat configuration files (server.xml) but since Spring Boot uses an embedded Tomcat instance (which is otherwise a huge convenience), I dont have access to the Tomcat configuration files (at least, not to my knowledge).

如果我可以访问 Tomcat 配置文件 ( server.xml),我可能会使其工作,但由于 Spring Boot 使用嵌入式 Tomcat 实例(这在其他方面非常方便),我无权访问 Tomcat 配置文件(至少,不能访问我的知识)。

There may be an application.propertiessetting for this but I haven't been able to track it down. I've seen references to a server.contextPathfield in application.propertiesthat I suspect may have something to do with replacement Tomcat config files. Even if it is related, I wouldn't know where to begin anyway -- all of the Tomcat SSL instructions I've seen start with editing an existing server.xmlfile, not building one from scratch.

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

Can this be done with Spring Boot (either by somehow specifying a snippet of server.xmlor through other means)? If not, what would be the simplest way to do this? I understand that I may need to exclude the Tomcat component of Spring Boot but I'd prefer to avoid that if possible.

这可以用 Spring Boot 完成吗(通过某种方式指定一个片段server.xml或通过其他方式)?如果不是,那么最简单的方法是什么?我知道我可能需要排除 Spring Boot 的 Tomcat 组件,但如果可能的话,我更愿意避免这种情况。

采纳答案by Dave

It turns out that there is a way to do this, although I'm not sure I've found the 'proper' way since this required hours of reading source code from multiple projects. In other words, this might be a lot of dumb work (but it works).

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

First, there is no way to get at the server.xml in the embedded Tomcat, either to augment it or replace it. This must be done programmatically.

首先,无法获取嵌入式 Tomcat 中的 server.xml,无法对其进行扩充或替换。这必须以编程方式完成。

Second, the 'require_https' setting doesn't help since you can't set cert info that way. It doesset up forwarding from http to https, but it doesn't give you a way to make https work so the forwarding isnt helpful. However, use it with the stuff below, which doesmake https work.

其次,“require_https”设置无济于事,因为您无法以这种方式设置证书信息。它确实设置了从 http 到 https 的转发,但它没有为您提供使 https 工作的方法,因此转发没有帮助。但是,将它与下面的内容一起使用,这确实可以使 https 工作。

To begin, you need to provide an EmbeddedServletContainerFactoryas explained in the Embedded Servlet Container Support docs. The docs are for Java but the Groovy would look pretty much the same. Note that I haven't been able to get it to recognize the @Valueannotation used in their example but its not needed. For groovy, simply put this in a new .groovy file and include that file on the command line when you launch springboot.

首先,您需要提供一个EmbeddedServletContainerFactory作为解释嵌入式Servlet容器支持文档。这些文档适用于 Java,但 Groovy 看起来几乎相同。请注意,我无法让它识别@Value示例中使用的注释,但不需要。对于 groovy,只需将其放在一个新的 .groovy 文件中,并在启动spring引导时将该文件包含在命令行中。

Now, the instructions say that you can customize the TomcatEmbeddedServletContainerFactoryclass that you created in that code so that you can alter web.xml behavior, and this is true, but for our purposes its important to know that you can also use it to tailor server.xmlbehavior. Indeed, reading the source for the class and comparing it with the Embedded Tomcat docs, you see that this is the only place to do that. The interesting function is TomcatEmbeddedServletContainerFactory.addConnectorCustomizers(), which may not look like much from the Javadocs but actually gives you the Embedded Tomcat object to customize yourself. Simply pass your own implementation of TomcatConnectorCustomizerand set the things you want on the given Connectorin the void customize(Connector con)function. Now, there are about a billion things you can do with the Connectorand I couldn't find useful docs for it but the createConnector()function in this this guys personal Spring-embedded-Tomcat projectis a very practical guide. My implementation ended up looking like this:

现在,说明说您可以自定义TomcatEmbeddedServletContainerFactory您在该代码中创建的类,以便您可以更改 web.xml 行为,这是正确的,但对于我们的目的,重要的是要知道您还可以使用它来定制server.xml行为。事实上,阅读类的源代码并将其与嵌入式 Tomcat 文档进行比较,您会发现这是唯一可以做到这一点的地方。有趣的功能是TomcatEmbeddedServletContainerFactory.addConnectorCustomizers(),它可能看起来不像 Javadocs,但实际上为您提供了嵌入式 Tomcat 对象来自定义您自己。只需传递您自己的实现TomcatConnectorCustomizerConnectorvoid customize(Connector con)函数中的给定上设置您想要的东西。现在,你可以用它做大约十亿件事情Connector,我找不到有用的文档,但是createConnector()这个功能在这个家伙个人的Spring-embedded-Tomcat项目中是一个非常实用的指南。我的实现最终看起来像这样:

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

The Autowiring will pick up this implementation an run with it. Once I fixed my busted keystore file (make sure you call keytool with -storetype pkcs12, not -storepass pkcs12as reported elsewhere), this worked. Also, it would be far better to provide the parameters (port, password, etc) as configuration settings for testing and such... I'm sure its possible if you can get the @Value annotation to work with Groovy.

Autowiring 将选择这个实现并运行它。一旦我修复了损坏的密钥库文件(确保您使用 调用 keytool -storetype pkcs12,而不是-storepass pkcs12其他地方报告的那样),这有效。此外,提供参数(端口、密码等)作为测试等的配置设置会好得多……我相信如果您可以获得 @Value 注释以与 Groovy 一起使用,那将是可能的。

回答by

Starting with Spring Boot 1.2, you can configure SSL using application.propertiesor application.yml. Here's an example for application.properties:

从 Spring Boot 1.2 开始,您可以使用application.properties或配置 SSL application.yml。下面是一个例子application.properties

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

Same thing with application.yml:

同样的事情application.yml

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

Here's a link to the current reference documentation.

这是当前参考文档的链接。

回答by pma

For external keystores, prefix with "file:"

对于外部密钥库,前缀为“file:”

server.ssl.key-store=file:config/keystore 

回答by guest

If you don't want to implement your connector customizer, you can build and import the library (https://github.com/ycavatars/spring-boot-https-kit) which provides predefined connector customizer. According to the README, you only have to create your keystore, configure connector.https.*, import the library and add @ComponentScan("org.ycavatars.sboot.kit"). Then you'll have HTTPS connection.

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