如何为HTTPS调用指定出站证书别名?

2022-09-02 09:36:34

我正在调用需要客户端证书身份验证的 Web 服务。

如果我指定一个包含单个证书(服务所需的客户机证书)的 Java 密钥库,那么一切正常。但是,如果我使用包含多个证书的密钥库,那么我似乎无法指定客户端应该选择哪个证书,客户端似乎选择了第一个可用的证书(按字母顺序)。

我尝试了以下属性,但没有预期的结果:

System.setProperty("com.sun.enterprise.security.httpsOutboundKeyAlias", "my-client-certificate alias");

如何指定应使用的客户端证书别名?


答案 1

Jakub在他的回复中提供的链接将引导您找到答案,但我想在这里发布一个更简单的回复,因为我们在最终获得有效的东西之前,已经为这个问题挣扎了很长一段时间。

我们的情况是,有多个证书可供使用,我们需要使用具有特定别名的证书来执行连接。我们通过创建自己的KeyManager实现来实现这一点,该实现将其大部分功能传递给默认的X509KeyManager,但具有在执行连接时准确选择要使用的正确别名的功能。

首先是我们创建的密钥管理器:

public class FilteredKeyManager implements X509KeyManager {

private final X509KeyManager originatingKeyManager;
private final X509Certificate[] x509Certificates;

public FilteredKeyManager(X509KeyManager originatingKeyManager, X509Certificate[] x509Certificates) {
    this.originatingKeyManager = originatingKeyManager;
    this.x509Certificates = x509Certificates;
}

public X509Certificate[] getCertificateChain(String alias) {
    return x509Certificates;
}

public String[] getClientAliases(String keyType, Principal[] issuers) {
    return new String[] {"DesiredClientCertAlias"};
}

实现所需的所有其他方法都是 到 的直通。originatingKeyManager

然后,当我们实际设置上下文时:

SSLContext context = SSLContext.getInstance("TLSv1");
context.init(new KeyManager[] { new FilteredKeyManager((X509KeyManager)originalKeyManagers[0], desiredCertsForConnection) },
    trustManagerFactory.getTrustManagers(), new SecureRandom());

希望这能说明问题,并为其他任何试图解决这个问题的人工作。


答案 2

简短的回答:它不能用默认的Java ssl实现来完成。

长答案:我研究了如何在.在其方法中称为 。它的实现实际上是以这样的方式完成的,即它们返回第一个别名,其条目与给定的密钥算法匹配,而几乎没有其他内容。没有办法调整别名选择。sun.security.ssl.ClientHandshakerserverHelloDoneX509ExtendedKeyManager.chooseClientAlias

对于那些可以更改代码的人来说,这看起来像是一个有希望的解决方法:http://www.44342.com/java-f392-t785-p1.htm