Ste*_*son 5 java ssl jsse client-certificates
JSSE允许用户通过指定javax.net.ssl.*参数来提供默认信任存储和密钥存储.我想为我的应用程序提供一个非默认的TrustManager,同时允许用户像往常一样指定KeyManager,但似乎没有任何方法可以实现这一点.
假设在unix机器上我想允许用户使用pkcs12密钥库进行身份验证,而在OS XI上则希望允许用户使用系统密钥链.在OS X上,应用程序可能会按如下方式启动:
java -Djavax.net.ssl.keyStore=NONE -Djavax.net.ssl.keyStoreType=KeychainStore \
-Djavax.net.ssl.keyStorePassword=- -jar MyApplication.jar
Run Code Online (Sandbox Code Playgroud)
这将很好地工作:当应用程序访问需要相互身份验证(客户端证书身份验证),那么用户将被提示允许访问自己的钥匙串HTTPS服务器.
现在假设我想将自签名证书颁发机构与我的应用程序捆绑在一起.我可以通过构造一个TrustManagerFactory并传入一个包含我的证书(javadoc)的KeyStore来覆盖默认的信任管理器.但是,要使用此非默认信任管理器,我需要创建并初始化SSLContext.这里存在问题.
通过调用init(..)并传递KeyManager和TrustManager 来初始化SSLContexts .但是,使用javax.net.ssl.*参数创建KeyManager的逻辑嵌入在默认SSLContexts的实现中 - 我找不到使用默认行为获取KeyManager或KeyManagerFactory的方法,同时还指定了非默认的TrustManager或TrustManagerFactory.因此,似乎是不可能的使用,例如,适当的操作系统特定钥匙扣实施,同时还提供用于认证远程服务器根证书.
听起来您面临着与此问题类似的问题,因为使用nulltrustmanager 参数会SSLContext.init(...)恢复为默认信任管理器,而它不会用于密钥管理器。
话虽这么说,使用默认系统属性初始化 KeyManager 并不难。像这样的东西应该可以工作(代码直接写在这个答案中,所以你可能需要修复一些小问题):
String provider = System.getProperty("javax.net.ssl.keyStoreProvider");
String keystoreType = System.getProperty("javax.net.ssl.keyStoreType", KeyStore.getDefaultType());
KeyStore ks = null;
if (provider != null) {
ks = KeyStore.getInstance(keystoreType, provider);
} else {
ks = KeyStore.getInstance(keystoreType);
}
InputStream ksis = null;
String keystorePath = System.getProperty("javax.net.ssl.keyStore");
String keystorePassword = System.getProperty("javax.net.ssl.keyStorePassword");
if (keystorePath != null && !"NONE".equals(keystorePath)) {
ksis = new FileInputStream(keystorePath);
}
try {
ks.load(ksis, keystorePassword.toCharArray());
} finally {
if (ksis != null) { ksis.close(); }
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, keystorePassword.toCharArray());
// Note that there is no property for the key password itself, which may be different.
// We're using the keystore password too.
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), ..., null);
Run Code Online (Sandbox Code Playgroud)
(更具体地说,这个实用程序类也可能令人感兴趣getKeyStoreDefaultLoader()。)
编辑:(根据您的补充评论)
恐怕当您只想自定义一半的SSLContext. 您在 Oracle JSSE 文档中链接到的部分说:“如果由 javax.net.ssl.keyStore 系统属性和适当的 javax.net.ssl.keyStorePassword 系统属性指定密钥库,则由默认 SSLContext 创建的 KeyManager将是用于管理指定密钥库的 KeyManager 实现。 ”这实际上并不适用于此,因为您使用的是自定义的SSLContext,而不是默认的(即使您正在自定义其中的一部分)。
无论如何,Oracle JSSE 参考指南和 IBM JSSE 参考指南在这个主题上有所不同。(我不确定其中有多少是“标准”的,以及原则上是否应该与另一个兼容,但情况显然并非如此。)
两个“创建SSLContext对象”部分几乎相同,但又有所不同。
Oracle JSSE 参考指南说:
如果 KeyManager[] 参数为 null,则将为该上下文定义一个空的 KeyManager。
IBM JSSE 参考指南说:
如果 KeyManager[] 参数为 null,则将搜索已安装的安全提供程序以查找 KeyManagerFactory 的最高优先级实现,从中获取适当的 KeyManager。
不幸的是,如果您希望具有不同规范的实现具有相同的行为,则必须编写一些代码,即使这实际上是重复其中一个实现已经执行的操作。
| 归档时间: |
|
| 查看次数: |
14985 次 |
| 最近记录: |