在Java中使用具有相同主机的多个SSL客户端证书

时间:2009-05-20 18:12:01

标签: java ssl certificate

在我的Java应用程序中,我需要使用SSL连接到同一主机,但每次都使用不同的证书。我需要使用不同证书的原因是远程站点使用证书中嵌入的用户ID属性来标识客户端。

这是一个在3个不同操作系统上运行的服务器应用程序,我需要能够在不重新启动过程的情况下切换证书。

Another user建议将多个证书导入同一个密钥库。但是,我不确定这对我有帮助,除非有办法告诉Java使用密钥库中的哪个证书。

3 个答案:

答案 0 :(得分:12)

SSL可以向客户端提供有关要呈现的证书的提示。此可能允许您使用一个具有多个身份的密钥存储区,但不幸的是,大多数服务器都不使用此提示功能。因此,如果您为每个连接指定要使用的客户端证书,它将更加健壮。

以下是使用指定的身份和信任存储设置一个SSLContext的示例代码。您可以重复这些步骤来创建多个上下文,每个上下文对应您要使用的每个客户端证书。每个SSLContext可能使用相同的信任库,但使用不同的标识存储(包含在该上下文中使用的单个客户机键条目)。

初始化您需要一次的上下文,并为每个连接重用正确的上下文。如果您要建立多个连接,这将允许您利用SSL会话。

KeyManagerFactory kmf = 
  KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(identityStore, password);
TrustManagerFactory tmf =
  TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

稍后,您可以直接创建套接字:

SSLSocketFactory factory = ctx.getSocketFactory();
Socket socket = factory.createSocket(host, port);

或者,如果您使用的是URL类,则可以指定在发出HTTPS请求时使用的SSLSocketFactory

HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setSSLSocketFactory(ctx.getSocketFactory());

Java 6有一些额外的API,可以根据您对密码套件等的偏好更容易地配置套接字。

答案 1 :(得分:0)

自从提出问题以来,实施方式可能已经发生了很大变化。我的理解是服务器将向客户端发送受信任的问题:

map()

然后客户端将收到一个CertificateRequest:

Found trusted certificate:
[
[
  Version: V3
  Subject: CN=localhost, OU=Spring, O=Pivotal, L=Holualoa, ST=HI, C=US
  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

然后,客户端将使用颁发者扫描其本地密钥库:

*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Cert Authorities:
<CN=localhost, OU=Spring, O=Pivotal, L=Holualoa, ST=HI, C=US>

如果found,它将使用该证书。

答案 2 :(得分:-1)

有一个解决方案here,用于从Axis客户端动态选择用于SSL身份验证的客户端证书。