【问题标题】:How to override Spring boot keystore/truststore for mutual SSL如何为相互 SSL 覆盖 Spring Boot 密钥库/信任库
【发布时间】:2019-11-28 10:26:51
【问题描述】:

我有一个 Spring Boot 应用程序。它的 application.yml 是从在线资源中获取的。它包含以下相互 SSL 的配置:

server:
  ssl:
    enabled: true
    client-auth: need
    key-store-type: PKCS12
    key-store: http://{config server url}/keystore.p12
    key-store-password: {keystore password}
    trust-store-type: JKS
    trust-store: http://{config server url}/truststore.jks
    trust-store-password: {truststore password}
  port: 8443

运行应用程序时出现此错误:

java.io.IOException: DerInputStream.getLength(): lengthTag=111, too big.
    at sun.security.util.DerInputStream.getLength(DerInputStream.java:599)
    at sun.security.util.DerValue.init(DerValue.java:391)
    at sun.security.util.DerValue.<init>(DerValue.java:332)
    at sun.security.util.DerValue.<init>(DerValue.java:345)
    at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1938)
    at java.security.KeyStore.load(KeyStore.java:1445)
    at org.apache.tomcat.util.security.KeyStoreUtil.load(KeyStoreUtil.java:69)
    at org.apache.tomcat.util.net.SSLUtilBase.getStore(SSLUtilBase.java:209)
    at org.apache.tomcat.util.net.SSLHostConfigCertificate.getCertificateKeystore(SSLHostConfigCertificate.java:206)
    at org.apache.tomcat.util.net.SSLUtilBase.getKeyManagers(SSLUtilBase.java:272)
    at org.apache.tomcat.util.net.SSLUtilBase.createSSLContext(SSLUtilBase.java:239)
    at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:97)
    ... 23 common frames omitted

但我可以通过编程方式打开密钥库和信任库。 (如下图)

private KeyStore getKeyStore() {
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    try (InputStream is = readCertificateFromURL(new URI(keyStoreURL))) {
        keyStore.load(is, keyStorePassword.toCharArray());
    }
    return keyStore();
}

private InputStream readCertificateFromURL(URI uri) throws IOException {
    RequestEntity<Void> requestEntity = RequestEntity.get(uri)
         .accept(org.springframework.http.MediaType.APPLICATION_OCTET_STREAM)
         .build();
    Resource resource = new RestTemplate().exchange(requestEntity,Resource.class).getBody();
    return resource.getInputStream();
}

如何告诉 Spring boot 选择这些密钥/信任库而不是 application.yml 中定义的那些?

我在网上找到的唯一内容是关于覆盖密钥库/信任库路径,而不是 KeyStore 对象本身。

【问题讨论】:

    标签: java spring spring-boot ssl mutual-authentication


    【解决方案1】:

    Spring属性中javax.net.ssl.trustStorejavax.net.ssl.keyStore的值及其对应的值需要是文件系统路径。如果您将它们复制到本地文件系统并引用它们,您的方法是否有效?

    【讨论】:

      【解决方案2】:

      正如@Toby 所要求的,它确实适用于本地文件。问题是商店是从配置服务器下载的,而不是作为二进制下载的。我最终实现了一个自定义 SslStoreProvider:

      @Bean
      public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatSslCustomizer() {
          return tomcat -> tomcat.setSslStoreProvider(new SslStoreProvider() {
      
              @Override
              public KeyStore getKeyStore() throws Exception {
                  KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                  try (InputStream is = readStoreFromURL(new URI(keyStoreURL))) {
                      keyStore.load(is, keyStorePassword.toCharArray());
                  }
                  return keyStore;
              }
      
              @Override
              public KeyStore getTrustStore() throws Exception {
                  KeyStore truststore = KeyStore.getInstance(trustStoreType);
                  try (InputStream is = readStoreFromURL(new URI(trustStoreURL))) {
                      truststore.load(is, trustStorePassword.toCharArray());
                  }
                  return truststore;
              }
      
              private InputStream readStoreFromURL(URI uri) {
                  // Download the stores as binary from the config server
              }
      
          });
      }
      

      【讨论】:

        猜你喜欢
        • 2017-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-18
        • 1970-01-01
        • 2021-01-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多