У меня следующая проблема. Я реализовал динамический обмен файлами trustore.jks на моем сервере с помощью ReloadableX509TrustManager. Проблема в том, что когда я перезагружаю сервер и пытаюсь подключить большое количество клиентов к моему серверу, не все клиенты подключаются сразу. Некоторые из них через некоторое время подключатся к серверу, и до этого я получаю такую ошибку:
2019-01-24 10: 03: 16,908 ОШИБКА c.s.Server [Тема-26]
javax.net.ssl.SSLException: получен close_notify во время рукопожатия
javax.net.ssl.SSLException: получено close_notify во время рукопожатия
at sun.security.ssl.Alerts.getSSLException (Alerts.java:208)
~ [?: 1.8.0_191] в
sun.security.ssl.SSLSocketImpl.fatal (SSLSocketImpl.java:1946)
~ [?: 1.8.0_191] в
sun.security.ssl.SSLSocketImpl.fatal (SSLSocketImpl.java:1898)
~ [?: 1.8.0_191] в
sun.security.ssl.SSLSocketImpl.recvAlert (SSLSocketImpl.java:1999)
~ [?: 1.8.0_191] в
sun.security.ssl.SSLSocketImpl.readRecord (SSLSocketImpl.java:1127)
~ [?: 1.8.0_191] в
sun.security.ssl.SSLSocketImpl.performInitialHandshake (SSLSocketImpl.java:1367)
~ [?: 1.8.0_191] в
sun.security.ssl.SSLSocketImpl.writeRecord (SSLSocketImpl.java:750)
~ [?: 1.8.0_191] в
sun.security.ssl.AppOutputStream.write (AppOutputStream.java:123)
~ [?: 1.8.0_191] в
java.io.ObjectOutputStream $ BlockDataOutputStream.drain (ObjectOutputStream.java:1877)
~ [?: 1.8.0_191] в
java.io.ObjectOutputStream $ BlockDataOutputStream.setBlockDataMode (ObjectOutputStream.java:1786)
~ [?: 1.8.0_191] в
java.io.ObjectOutputStream. (ObjectOutputStream.java:247)
~ [?: 1.8.0_191] в
api.server.Server $ ConnectionClientRepresentation.run (Server.java:254)
[Serwer_szy_res_adr.jar:]
И иногда я тоже получаю следующую ошибку:
2019-01-24 12: 56: 43,715 ОШИБКА c.s.Server [Thread-429066]
javax.net.ssl.SSLException: нераспознанное сообщение SSL, открытый текст
связь? javax.net.ssl.SSLException: нераспознанное сообщение SSL,
текстовое соединение? в
sun.security.ssl.InputRecord.handleUnknownRecord (InputRecord.java:710)
~ [?: 1.8.0_191] в
sun.security.ssl.InputRecord.read (InputRecord.java:527) ~ [?: 1.8.0_191]
at sun.security.ssl.SSLSocketImpl.readRecord (SSLSocketImpl.java:975)
~ [?: 1.8.0_191] в
sun.security.ssl.SSLSocketImpl.performInitialHandshake (SSLSocketImpl.java:1367)
~ [?: 1.8.0_191] в
sun.security.ssl.SSLSocketImpl.writeRecord (SSLSocketImpl.java:750)
~ [?: 1.8.0_191] в
sun.security.ssl.AppOutputStream.write (AppOutputStream.java:123)
~ [?: 1.8.0_191] в
java.io.ObjectOutputStream $ BlockDataOutputStream.drain (ObjectOutputStream.java:1877)
~ [?: 1.8.0_191] в
java.io.ObjectOutputStream $ BlockDataOutputStream.setBlockDataMode (ObjectOutputStream.java:1786)
~ [?: 1.8.0_191] в
java.io.ObjectOutputStream. (ObjectOutputStream.java:247)
~ [?: 1.8.0_191] в
api.server.Server $ ConnectionClientRepresentation.run (Server.java:254)
[Serwer_szyf_res_adr.jar:]
Моя реализация сервера:
class ReloadableX509TrustManager implements X509TrustManager {
private final String trustStorePath;
private X509TrustManager trustManager;
public ReloadableX509TrustManager(String pathToTrustStore) throws Exception {
this.trustStorePath = pathToTrustStore;
reloadTrustManager();
}
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
try {
reloadTrustManager();
} catch (Exception e) {
e.printStackTrace();
}
String username = x509Certificates[0].getSubjectDN().getName().split("CN=")[1].split(",")[0];
x509Certificates[0].checkValidity();
System.out.println("Trying to connect : " + username);
trustManager.checkClientTrusted(x509Certificates, s);
x509Certificates[0].checkValidity();
System.out.println("User " + username + " signed in, you are authenticated!");
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
// trustManager.checkServerTrusted(x509Certificates, s);
}
@Override
public X509Certificate[] getAcceptedIssuers() {
X509Certificate[] issuers = trustManager.getAcceptedIssuers();
return issuers;
}
private void reloadTrustManager() throws Exception {
KeyStore trustStore = KeyStore.getInstance("JKS");
InputStream in = new FileInputStream(trustStorePath);
try {
trustStore.load(in, TRUSTSTORE_PASSWORD.toCharArray());
} finally {
in.close();
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
trustManagerFactory.init(trustStore);
TrustManager trustManagers[] = trustManagerFactory.getTrustManagers();
for (int i = 0; i < trustManagers.length; i++) {
if (trustManagers[i] instanceof X509TrustManager) {
trustManager = (X509TrustManager) trustManagers[i];
return;
}
}
throw new NoSuchAlgorithmException("No X509TrustManager in TrustManagerFactory");
}
}
public void run() {
try {
createSSLServerSocketFactory();
SSLServerSocket ss = (SSLServerSocket) factory.createServerSocket(port);
while (true) {
SSLSocket s = (SSLSocket) ss.accept();
s.setNeedClientAuth(true);
try {
ConnectionClientRepresentation connection = new ConnectionClientRepresentation(s);
connection.start();
} catch (Exception e) {
try {
s.close();
} catch (IOException e1) {
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void createSSLServerSocketFactory() {
try {
factory = getSSLContext(TRUSTSTORE_PATH).getServerSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
}
public SSLContext getSSLContext(String pathToTrustStore) throws Exception {
InputStream keyStoreInputStream = new FileInputStream(KEYSTORE_PATH);
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(keyStoreInputStream, KEYSTORE_PASSWORD.toCharArray());
keyStoreInputStream.close();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, KEYSTORE_PASSWORD.toCharArray());
TrustManager[] trustManagers = new TrustManager[]{
new ReloadableX509TrustManager(pathToTrustStore)
};
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagers, new SecureRandom());
return sslContext;
}
И реализация на стороне клиента:
private void createSSSLSocketFactory() {
try {
InputStream keyStoreInputStream = new FileInputStream(KEYSTORE_PATH);
InputStream trustStoreInputStream = new FileInputStream(TRUSTSTORE_PATH);
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(keyStoreInputStream, KEYSTORE_PASSWORD.toCharArray());
keyStoreInputStream.close();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, KEYSTORE_PASSWORD.toCharArray());
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(trustStoreInputStream, TRUSTSTORE_PASSWORD.toCharArray());
trustStoreInputStream.close();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
trustManagerFactory.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
factory = sslContext.getSocketFactory();
} catch (IOException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
try {
s = (SSLSocket) factory.createSocket(serverIP, serverPort);
s.startHandshake();
oos = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
...
}
}
}