Ссылки, которые 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());
Надеюсь, это прояснит ситуацию и сработает для всех, кто пытается решить эту проблему.