如何将 .pem SSL 证书用于作为 Spring Boot 应用程序开发的 REST API

问题描述 投票:0回答:5

我们有一个用于 REST Web 服务的 Spring Boot 应用程序,该应用程序仍在开发中。 我们现在使用自签名证书。

现在,它将与另外 1 个已开发的应用程序一起部署到系统中。 这个预先存在的应用程序默认使用自签名证书,但为客户提供了上传 CA 证书的选项(如果需要)。现在,我们想为这个新应用程序使用相同的证书。

基本上,我们希望客户端对在 1 个系统中运行的 2 个应用程序使用 1 个证书。

现在,这个现有应用程序具有 .pem 和 .cer 等证书文件。
如何在使用 jks 格式证书的 Spring Boot 应用程序中使用此证书?

当然,如果有任何更新,证书应该可供两个应用程序使用。

java spring spring-boot ssl ca
5个回答
11
投票

从 Spring Boot 2.7 开始,可以使用 PEM 编码的证书和私钥文件。
请参阅下面的示例(PKCS8 格式的私钥)。

server:
  port: 8443
  ssl:
    certificate: "classpath:my-cert.crt"
    certificate-private-key: "classpath:my-cert.key"
    trust-certificate: "classpath:ca-cert.crt"

Spring 文档 2.7.2


5
投票

PEM 是一种众所周知的证书文件格式。除了 Java 之外。由于 Java 仅使用 JKS(其仅限 Java 的二进制密钥库)或 PKCS12 作为密钥和证书。因此,我们必须将 PEM 编码的证书转换为 JKS 或 PKCS12,以便 Java 可以使用它。但在很多情况下这可能很丑陋。

您可以在 spring-boot 应用程序中使用以下依赖项。

<dependency>
  <groupId>de.dentrassi.crypto</groupId>
  <artifactId>pem-keystore</artifactId>
  <version>2.0.0</version>
</dependency>

然后添加

KeyStore keyStore = KeyStore.getInstance("PEM");

了解更多信息

https://github.com/ctron/pem-keystore

application.properties

 server.ssl.enabled=true
 server.ssl.key-store=/path/to/keystore.properties
 server.ssl.key-store-type=PEMCFG
 server.ssl.key-store-password=dummy
 server.ssl.key-alias=keycert

然后创建文件

keystore.properties
:

alias=keycert
source.cert=/etc/…/fullchain.pem
source.key=/etc/…/privkey.pem

0
投票

我经常做的就是在 Spring 中用 Jetty 替换 Tomcat,它允许自定义 ssl 配置。通过这种设置,可以进行任何类型的自定义,例如处理 pem 文件,但也可以处理特别加密的 pem 文件。以下是我使用的设置:

下面将加载 pem 文件并创建 KeyManager TrustManager。这将用于创建 SSLFactory,而 SSLFactory 将用于转换为 Jetty 兼容的 ssl 配置。

import nl.altindag.ssl.SSLFactory;
import nl.altindag.ssl.util.JettySslUtils;
import nl.altindag.ssl.util.PemUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.X509ExtendedTrustManager;

@Configuration
public class SSLConfig {

    @Bean
    public SSLFactory sslFactory() {
        X509ExtendedKeyManager keyManager = PemUtils.loadIdentityMaterial("chain.pem", "private-key.pem", "my-password".toCharArray());
        X509ExtendedTrustManager trustManager = PemUtils.loadTrustMaterial("some-trusted-certificate.pem");

        return SSLFactory.builder()
                .withIdentityMaterial(keyManager)
                .withTrustMaterial(trustManager)
                .build();
    }

    @Bean
    public SslContextFactory.Server sslContextFactory(SSLFactory sslFactory) {
        return JettySslUtils.forServer(sslFactory);
    }

}

Jetty SSL 配置需要传递到服务器配置:

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Collections;

@Configuration
public class ServerConfig {

    @Bean
    public ConfigurableServletWebServerFactory webServerFactory(SslContextFactory.Server sslContextFactory, @Value("${server.port}") int serverPort) {
        JettyServletWebServerFactory factory = new JettyServletWebServerFactory();

        JettyServerCustomizer jettyServerCustomizer = server -> {
            ServerConnector serverConnector = new ServerConnector(server, sslContextFactory);
            serverConnector.setPort(serverPort);
            server.setConnectors(new Connector[]{serverConnector});
        };
        factory.setServerCustomizers(Collections.singletonList(jettyServerCustomizer));

        return factory;
    }

}

在这两个java配置之后,你还需要告诉Spring不要使用Tomcat,而应该使用Jetty。这可以通过以下 pom 配置来完成:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot</artifactId>
    <version>2.7.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.7.5</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
    <version>2.7.5</version>
</dependency>

我使用自己的库来读取 pem 文件。请参阅下面的依赖项,并在此处了解有关其他用法的更多信息:SSLContext-Kickstart

<dependency>
    <groupId>io.github.hakky54</groupId>
    <artifactId>sslcontext-kickstart-for-jetty</artifactId>
    <version>8.1.2</version>
</dependency>
<dependency>
    <groupId>io.github.hakky54</groupId>
    <artifactId>sslcontext-kickstart-for-pem</artifactId>
    <version>8.1.2</version>
</dependency>

0
投票

可以从证书和私钥创建 JKS 文件(pem 格式),如下

#Combine private key and certificate to create pkcs12 file
openssl pkcs12 -export -out keystore.p12 -inkey privatekey.pem -in certificate.crt -name your_alias

#Import the certificate and key into a JKS file for Java to use
keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -destkeystore keystore.jks -deststoretype JKS

-3
投票

为了测试安全 API,您可以使用 Fiddler,这是一个绕过或伪造 SSL 的工具。

(或)

您可以像下面这样配置应用程序属性。

server.port: 8443
security.require-ssl=true
server.ssl.key-store:/etc/letsencrypt/live/seeld.eu/keystore.p12
server.ssl.key-store-password: <your-password>
server.ssl.keyStoreType: PKCS12
server.ssl.keyAlias: tomcat
© www.soinside.com 2019 - 2024. All rights reserved.