【问题标题】:Spring boot ssl how to trust all valid certificatesSpring Boot ssl如何信任所有有效证书
【发布时间】:2019-12-26 07:48:23
【问题描述】:

我在我的 Spring Boot 应用程序中启用了 ssl,并且任何时候我想使用像 googleapis 或 facebook 这样的 Rest 服务,我都必须在信任库中添加证书。

我使用openssl获取证书:

openssl s_client -connect googleapis.com:443

然后我将它导入到信任库中:

keytool.exe -import -noprompt -trustcacerts -alias googleapis.com -file googleapis.com.cer -keystore app-server.p12 -storepass *****

问题是管理起来很不方便,当证书过期时,我每次都必须更新信任库中的证书。

此外,即使我添加了正确的证书,有时也会出现错误:

引起:javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:PKIX 路径构建失败: sun.security.provider.certpath.SunCertPathBuilderException:无法 找到请求目标的有效认证路径

我知道这些证书是有效的,是否可以自动信任它们而不将它们添加到信任库中?

这是我的 ssl 配置

  ssl:
    enabled: true
    key-store: classpath:keystore/app-server.p12
    key-store-password: ******
    key-alias: app-server
    key-store-type: PKCS12
    trust-store: classpath:keystore/app-server.p12
    trust-store-password: *****
    trust-store-type: PKCS12
    keyStorePath: config/keystore/app-server.p12

我还必须在 main 方法中添加系统属性

private static String keyStorePath;

private static String keyStorePassword;


@Value("${server.ssl.keyStorePath}")
public void setKeyStorePath(String keyStorePath) {
    ClientUiApplication.keyStorePath = keyStorePath;
}

@Value("${server.ssl.key-store-password}")
public void setKeyStorePassword(String keyStorePassword) {
    ClientUiApplication.keyStorePassword = keyStorePassword;
}

public static void main(String[] args) {

    SpringApplication.run(ClientUiApplication.class, args);
    System.setProperty("javax.net.ssl.trustStore", keyStorePath);
    System.setProperty("javax.net.ssl.trustStorePassword", keyStorePassword);
}

另一个重要的细节,我需要一个信任库,因为我使用由 Keytool 生成的自签名证书。否则,我的服务将无法相互通信。

【问题讨论】:

  • 为什么不喜欢?我的问题有什么问题?
  • @wargre 好的,这只是通常的 ssl 配置,所以我认为没有必要。

标签: spring-boot ssl


【解决方案1】:

你给代码:

public static void main(String[] args) {
    SpringApplication.run(ClientUiApplication.class, args);
    System.setProperty("javax.net.ssl.trustStore", keyStorePath);
    System.setProperty("javax.net.ssl.trustStorePassword", keyStorePassword);
}

这意味着您强制 java 信任库成为您提供的信任库。默认信任库不再使用。

所以,是的,您必须在此信任库中添加所有需要的根证书,以免出现您描述的问题。

为什么需要有一个特定的信任库?

  • 如果没有用,请将其删除。
  • 如果您有必须信任的特定附加证书,最好将此证书添加到默认信任存储区(jre/lib/security/cacerts 文件)

【讨论】:

  • 谢谢,我在 main 方法中使用了该配置,因为 Eureka 需要它,但我不确定我是否仍然需要它,因为我不再使用 Eureka(现在仅 Kubernetes)。但是我仍然需要一个信任来允许我的服务与 Feign 在 ssl 下进行通信,因为我的服务使用自签名证书。在具有有效证书的生产环境中,我可能不需要信任,我不使用服务之间的受限通信。我不知道默认的 java trustore 和我配置的有什么区别。
  • 我们去找答案吧。首先,默认的 java 信任库(cacerts)包含很多根证书(例如全局签名,让我们加密,digicert...),这样 java 可以毫无问题地访问很多 https 网站。您使用的信任库是您从无到有创建的信任库。例如,如果您信任 let's encrypt 根证书,您将能够访问很多服务(包括 stackoverflow)。如果您只信任当前的 stackoverflow 证书,您将能够访问 stackoverflow,直到 stackoverflow 证书轮换
  • 请注意,您说您使用的是 kubernetes。对于您所描述的,您想将 https 用于内部服务。如果您想保护您的集群,这是完全合法的。今天,尤其是使用 kubernetes,您可以使用执行 mtls 策略的服务网格。这意味着您的应用程序会说和听 http,但数据是在线上使用 TLS 加密的。这意味着它在应用程序方面更简单,但在操作方面有点复杂(一些工具可以从广泛的列表中检查:istio、linkerd、maech...)
  • 好的,谢谢您提供这些信息,我不知道自己是 ssl 机制的初学者。我会发现 mtls 它似乎是一个有趣的工具。
【解决方案2】:

您还可以使用 CloseableHttpClient 绕过 SSL 证书检查

public static CloseableHttpClient getCloseableHttpClient()
{
    CloseableHttpClient httpClient = null;
    try {
        httpClient = HttpClients.custom().
                setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).
                setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy()
                {
                    public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
                    {
                        return true;
                    }
                }).build()).build();
    } catch (KeyManagementException e) {
        LOGGER.error("KeyManagementException in creating http client instance", e);
    } catch (NoSuchAlgorithmException e) {
        LOGGER.error("NoSuchAlgorithmException in creating http client instance", e);
    } catch (KeyStoreException e) {
        LOGGER.error("KeyStoreException in creating http client instance", e);
    }
    return httpClient;
}

它会自动信任所有证书并将您从 SSLHandshakeException: sun.security.validator.ValidatorException

中解救出来

注意在生产环境中不推荐这种方法

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-07
    • 2015-04-16
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-22
    相关资源
    最近更新 更多