在 Java 中选择 SSL 客户端证书

新手上路,请多包涵

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

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

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

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

这篇文章 表明可以从密钥库中选择一个单独的证书,但是如何将它附加到请求中似乎是一个完全不同的问题。

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

原文由 Carlos 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 763
2 个回答

Java SSL 客户端只会在服务器请求时发送证书。服务器可以发送关于它将接受哪些证书的可选提示;如果客户有多个证书,这将帮助客户选择一个证书。

通常,一个新的 SSLContext 使用特定的客户端证书创建,并且 Socket 实例是从从该上下文获得的工厂创建的。不幸的是,Axis2 似乎不支持使用 SSLContext 或自定义 SocketFactory 。它的客户端证书设置是全局的。

原文由 erickson 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

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

如果这有帮助,您可能会发现使用 jSSLutils(及其包装器) 来配置 SSLContext (这些主要是构建 SSLContext 的帮助程序类)。 (注意这个例子是选择服务器端的别名,但是可以适配, 源代码可用。)

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

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

或者,根据 此 Axis 2 文档,Axis 2 似乎使用 Apache HTTP Client 3.x:

如果要执行 SSL 客户端身份验证(2 向 SSL),可以使用 HttpClient 的 Protocol.registerProtocol 功能。您可以覆盖“https”协议,或者如果您不想与常规 https 混淆,则可以为 SSL 客户端身份验证通信使用不同的协议。在 http://jakarta.apache.org/commons/httpclient/sslguide.html 找到更多信息

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

原文由 Bruno 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题