在 Java 中选择 SSL 客户端证书

2022-09-01 19:21:32

我们的系统与多个网络服务提供商进行通信。它们都是从单个 Java 客户机应用程序调用的。到目前为止,所有 Web 服务都已通过 SSL,但没有一个使用客户端证书。好吧,一个新的合作伙伴正在改变这一点。

使应用程序使用证书进行调用很容易;设置,并会这样做。但是,现在的问题是如何使它仅在调用该特定 Web 服务时使用证书。我想更一般地说,我们希望能够选择要使用的客户端证书(如果有的话)。javax.net.ssl.keyStorejavax.net.ssl.keyStorePassword

一种快速解决方案可能是设置系统属性,调用方法,然后取消设置它们。唯一的问题是我们正在处理一个多线程应用程序,所以现在我们需要处理同步或锁定或其他问题。

每个服务客户端都应该彼此完全独立,并且它们单独打包在单独的 JAR 中。因此,我想到的一个选择(尽管我们还没有正确分析它)是以某种方式隔离每个JAR,也许将每个JAR加载到具有不同参数的不同VM下。这只是一个我不知道如何实现的想法(或者如果可能的话,就此而言)。

这篇文章建议可以从密钥存储中选择单个证书,但是如何将其附加到请求似乎是一个完全不同的问题。

我们使用 Java 1.5、Axis2 和用 或 生成的客户端类。wsimportwsdl2java


答案 1

配置是通过 一个 来完成的,它实际上是 (or ) 的工厂。默认情况下,这将从属性进行配置。此外,当服务器请求证书时,它会发送一条 TLS/SSL 消息,其中包含它愿意接受的 CA 可分辨名称的列表。虽然这个列表严格来说只是指示性的(即服务器可以接受来自不在列表中的颁发者的证书,或者可以拒绝列表中CA的有效证书),但它通常以这种方式工作。SSLContextSSLSocketFactorySSLEnginejavax.net.ssl.*CertificateRequest

默认情况下,在配置中的证书选择器(同样你通常不必担心它),将选择一个证书,该证书已由列表中的一个颁发(或可以链接到那里的颁发者)。该列表是 X509KeyManager.chooseClientAlias 中的参数(是要选取的证书的别名,在密钥库中称为该别名)。如果您有多个候选项,则还可以使用该参数,如果这有助于做出选择,它将为您提供对等方的 IP 地址。X509KeyManagerSSLContextissuersaliassocket

如果这有帮助,你可能会发现使用jSSLutils(及其包装器)来配置你的(这些主要是构建s的帮助器类)。(请注意,此示例用于选择服务器端别名,但可以进行调整,源代码可用SSLContextSSLContext

完成此操作后,您应该查找有关 Axis(和 SecureSocketFactory)中的 axis.socketSecureFactory系统属性的文档。如果你看一下Axis源代码,构建一个从你选择的SSLContext初始化的org.apache.axis.components.net.SunJSSESocketFactory应该不会太困难(请参阅这个问题)。

刚刚意识到您正在谈论Axis2,那里似乎已经消失了。您也许能够使用默认找到解决方法,但这会影响您的整个应用程序(这不是很好)。如果使用 jSSLutils 的 X509KeyManagerWrapper,则可以使用默认值并仅将某些主机视为例外。(这不是一个理想的情况,我不确定如何在轴2中使用自定义/。SecureSocketFactorySSLContextX509KeyManagerSSLContextSSLSocketFactory

或者,根据此Axis 2文档,看起来Axis 2使用Apache HTTP Client 3.x:

如果要执行 SSL 客户端身份验证(双向 SSL),可以使用 HttpClient 的 Protocol.registerProtocol 功能。您可以覆盖“https”协议,或者如果您不想弄乱常规https,则可以对SSL客户端身份验证通信使用其他协议。在 http://jakarta.apache.org/commons/httpclient/sslguide.html 了解更多信息

在这种情况下,SslContextedSecureProtocolSocketFactory 应该可以帮助您配置 .SSLContext


答案 2

Java SSL 客户机仅在服务器请求时才发送证书。服务器可以发送有关它将接受哪些证书的可选提示;这将有助于客户端选择单个证书(如果它具有多个证书)。

通常,使用特定的客户端证书创建新实例,并从从该上下文获取的工厂创建实例。遗憾的是,Axis2 似乎不支持使用 或 自定义 。其客户端证书设置是全局的。SSLContextSocketSSLContextSocketFactory