Этот вопрос похож на этот: как установить разные хранилище ключей хранилища доверенных сертификатов с установленным свойством
У меня есть локальный файл cacerts чтобы я «1024 *» «слил» с файлом по умолчанию cacerts , чтобы все сертификаты в обоих файлах были доступны для проверки действительности SSL на сервере LDAP. На разных постах я успешно создавал новый TrustStore
объект, содержащий все сертификаты, а затем установил TrustStore
для использования SSLContext.init
.
Это будет правильным вплоть до того, как я вызову InitialDirContext(env)
который пытается установить соединение LDAPS. Посмотрев в отладчике метод X509TrustManagerImpl.checkTrusted (…), мои локальные сертификаты больше не включаются в проверяемые, и соединение не устанавливается. Это как если бы вызов InitialDirContext(env)
снова сбрасывал TrustStore
на значение по умолчанию. Как я могу сохранить свой пользовательский TrustStore
в течение всей этой транзакции SSL?
Обновление: я подозреваю, что мне нужно установить SSLSocketFactory на sslContext.getSocketFactory (), но я не нашел ни одного кода, который делает это, кроме http-соединения (это не так).
Вот код:
try {
// create a custom KeyStore object from our app keystore file
char[] keystorePW = "changeit".toCharArray();
InputStream keystoreStream = viperUI.Controller.class.getResourceAsStream(keystoreFilePath);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(keystoreStream, keystorePW);
// Add default Root CA certificates (generally, from JAVA_HOME/lib/cacerts) to trust store
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore)null);
for (TrustManager trustManager : trustManagerFactory.getTrustManagers()) {
if (trustManager instanceof X509TrustManager) {
for (X509Certificate acceptedIssuer : ((X509TrustManager) trustManager).getAcceptedIssuers()) {
keystore.setCertificateEntry(acceptedIssuer.getSubjectDN().getName(), acceptedIssuer);
}
}
}
// Convert the trust store to trust managers
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keystore);
tm = tmf.getTrustManagers();
// set the SSL/TLS context using this TrustManager
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tm, null); // <-- all appears well here
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | IOException | CertificateException e) {
e.printStackTrace();
}
}
// create environment properties for the ldap connection
try {
env.put(Context.INITIAL_CONTEXT_FACTORY, getLDAPPropertyValue(INITIAL_CONTEXT_FACTORY));
env.put(Context.PROVIDER_URL, getLDAPPropertyValue(CONNECTION_URL));
env.put("com.sun.jndi.ldap.connect.timeout", connectionTimeout);
if (isLoginPropertySet(CONNECTION_USERNAME)) {
env.put(Context.SECURITY_PRINCIPAL, getLDAPPropertyValue(CONNECTION_USERNAME));
}
if (getLDAPPropertyValue(CONNECTION_URL).toUpperCase().startsWith("LDAPS://")) {
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
}
PrintWriter writer = new PrintWriter(System.out);
log("\n======================= ldap parameters ====================");
env.list(writer); // print the list with a PrintWriter object
writer.flush();
log("======================= ldap parameters ====================\n");
// create the password last so it doesn't print above
if (isLoginPropertySet(CONNECTION_PASSWORD)) {
env.put(Context.SECURITY_CREDENTIALS, getLDAPPropertyValue(CONNECTION_PASSWORD));
}
// attempt the ldap authentication
context = new InitialDirContext(env); // <-- the TrustStore seems to change here
log("[LoginModule] initial connection using service account successful!");
} catch (NamingException e) {
log("[LoginModule] " + e.toString());
throw e;
}