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

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

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

另一位用户建议将多个证书导入同一个密钥库。 但是,我不确定这会对我有所帮助,除非有办法告诉Java要在密钥库中使用哪个证书。

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

以下是设置具有指定标识和信任存储的一个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,可以根据您对密码套件等的偏好更容易地配置套接字。

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