【发布时间】:2013-02-22 13:07:25
【问题描述】:
概述
JSSE 允许用户通过指定 javax.net.ssl.* 参数来提供默认的信任库和密钥库。我想为我的应用程序提供一个非默认的 TrustManager,同时允许用户像往常一样指定 KeyManager,但似乎没有任何方法可以实现这一点。
详情
假设在 unix 机器上我希望允许用户使用 pkcs12 密钥库进行身份验证,而在 OS X 上我希望允许用户使用系统钥匙串。在 OS X 上,应用程序可能会按如下方式启动:
java -Djavax.net.ssl.keyStore=NONE -Djavax.net.ssl.keyStoreType=KeychainStore \
-Djavax.net.ssl.keyStorePassword=- -jar MyApplication.jar
这可以正常工作:当应用程序访问需要相互身份验证(客户端证书身份验证)的 https 服务器时,将提示用户允许访问他们的钥匙串。
问题
现在假设我想将自签名证书颁发机构与我的应用程序捆绑在一起。我可以通过构造一个 TrustManagerFactory 并传入一个包含我的证书 (javadoc) 的 KeyStore 来覆盖默认信任管理器。但是,要使用这个非默认信任管理器,我需要创建和初始化 SSLContext。问题就在这里。
通过调用init(..) 并同时传递 KeyManager 和 TrustManager 来初始化 SSLContext。但是,使用 javax.net.ssl.* 参数创建 KeyManager 的逻辑嵌入在默认 SSLContexts 的实现中——我找不到使用默认行为获取 KeyManager 或 KeyManagerFactory 的方法,同时还指定了非默认 TrustManager 或 TrustManagerFactory。因此,似乎不可能使用例如适当的操作系统特定的钥匙串实现,同时还提供用于验证远程服务器的根证书。
【问题讨论】:
-
澄清一下,我不想重新实现默认行为(例如,通过复制 sun.security.ssl.SSLContextImpl 或 javax.net.ssl.DefaultSSLContext 的实现)作为默认加载行为在不同平台上可能会有所不同,并且可能会在未来的 JVM 版本中发生变化。我正在专门寻找一种重用默认行为的方法,例如通过从默认 SSLContext 中提取 KeyManager。
标签: java ssl client-certificates jsse