在 Java(JSEE) 中获取默认系统信任库的 SSLContext

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30519267/
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-11-02 17:15:29  来源:igfitidea点击:

Get SSLContext for default system truststore in Java(JSEE)

javasecurityssldefault

提问by vkolodrevskiy

I've been using custom keystore in my program by specifying javax.net.ssl.keyStore, javax.net.ssl.keyStorePassword, javax.net.ssl.trustStore, javax.net.ssl.trustStorePassword. My truststore contains self-signed certificates. Now I want to make some https request(say to https://google.com) and use default jre system trusstore that contains information about different CAs. To make http requests I use OkHttp library. Its client has an option to specify SslSocketFactory, but to get it I need to initialise SSLContextfor default jre truststore. How can I do that?

我一直在我的程序中使用自定义密钥库,方法是指定javax.net.ssl.keyStorejavax.net.ssl.keyStorePasswordjavax.net.ssl.trustStorejavax.net.ssl.trustStorePassword。我的信任库包含自签名证书。现在我想发出一些 https 请求(比如https://google.com)并使用包含有关不同 CA 的信息的默认 jre 系统 trusstore。为了发出 http 请求,我使用 OkHttp 库。它的客户端可以选择指定SslSocketFactory,但要获得它,我需要为默认的 jre 信任库初始化SSLContext。我怎样才能做到这一点?

UPDATE: The code I went with is

更新:我使用的代码是

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

    // load default jvm keystore
    keyStore.load(new FileInputStream(
            System.getProperties()
                  .getProperty("java.home") + File.separator
                + "lib" + File.separator + "security" + File.separator
                + "cacerts"), "changeit".toCharArray());

    TrustManagerFactory tmf = TrustManagerFactory.getInstance(
            TrustManagerFactory.getDefaultAlgorithm());

    tmf.init(keyStore);

    SSLContext ctx = SSLContext.getInstance("TLS");

    ctx.init(null, tmf.getTrustManagers(), new SecureRandom());

采纳答案by Bruno

The javax.net.ssl.*system properties will affect the default SSLContext, the one used by SSLSocketFactory.getDefault()and the one returned by SSLContext.getDefault(), if you haven't used SSLContext.setDefault(...)using a custom context, that is.

javax.net.ssl.*系统属性将影响默认SSLContext,一个是使用SSLSocketFactory.getDefault()和一个由归国SSLContext.getDefault(),如果你还没有使用SSLContext.setDefault(...)使用自定义背景,那就是。

If you want to keep the ability to use the default truststore for some connections (not not the ones where you use these self-signed certs), you shouldn't use those properties. Instead you should make the other connections use an SSLContextbuilt for those self-signed certs. (You can't really get the default trust store with certainty otherwise, at least not without using the private API in the JRE.)

如果您想保留对某些连接使用默认信任库的能力(不是那些使用这些自签名证书的连接),则不应使用这些属性。相反,您应该让其他连接使用SSLContext为这些自签名证书构建的。(否则您无法真正确定地获得默认信任存储,至少在不使用 JRE 中的私有 API 的情况下不会。)

Since the library you're using allows you to specify an SSLSocketFactory, build one from your custom SSLContextwhen you want to use it. (You can also build one from the default SSLContextfor the other cases if needed, although that's often implied, if that library resets its settings between connections.)

由于您使用的库允许您指定一个SSLSocketFactory,SSLContext在您想使用它时从您的自定义构建一个。(SSLContext如果需要,您也可以从默认情况下为其他情况构建一个,尽管这通常是暗示的,如果该库在连接之间重置其设置。)

回答by Dave Mulligan

You use the default trust store by not specifying a different one. If you omit the javax.net.ssl.trustStoreand the javax.net.ssl.trustStorePasswordparameters, you will use the default values. (Which, for reference, are $JAVA_HOME/jre/lib/security/cacertsand changeit(yes, really)).

您可以通过不指定其他信任库来使用默认信任库。如果省略javax.net.ssl.trustStorejavax.net.ssl.trustStorePassword参数,则将使用默认值。(作为参考,它们是$JAVA_HOME/jre/lib/security/cacertschangeit(是的,真的))。