#java #android #ssl #kuzzle
#java #Android #ssl #kuzzle
Вопрос:
Я использую Kuzzle с его Android SDK (3.0.10) для получения уведомлений с помощью системы pub / sub.
В Android 5 и 6, когда я пытаюсь подключиться к серверу, выполняется обратный вызов с ошибкой с сообщением: {«сообщение»: «Рукопожатие SSL прервано: ssl = 0x7f382c540280: ошибка ввода-вывода во время системного вызова, сброс соединения одноранговым узлом»}
В других версиях Android это работает отлично.
Options options = new Options();
options.setPort(443);
options.setOfflineMode(Mode.AUTO);
options.setSsl(true);
kuzzle = new Kuzzle(kuzzleHost, options, new ResponseListener<Void>() {
@Override
public void onSuccess(Void response) {
initSubscriptions();
}
@Override
public void onError(JSONObject error) {
Log.e("Kuzzle", "error");
}
});
} catch (Exception e) {
Utils.caughtException(KuzzleSub.class.getSimpleName(), e);
}
зависимости app / build.gradle
dependencies {
implementation 'io.kuzzle:sdk-android:3.0.10'
implementation 'tech.gusavila92:java-android-websocket-client:1.2.2'
Отключаю Kuzzle и gusavila92.websocketclient.Классы WebSocketClient Я обнаружил, что в Android 5 протоколами с поддержкой websocket являются SSLv3, TLSv1, TLSv1.1, TLSv1.2. Однако в Android 7 и более поздних версиях SSLv3 не включен.
Поиск в Интернете я нашел несколько решений, таких как отключить SSLv3, включить только TLSv1.2, создать новый SSLFactory. Приведенный ниже код — это моя попытка использовать другой SSLFactory, создающий класс, который расширяет Kuzzle.java и SSLFactory.java
public class ExtendedKuzzle extends Kuzzle {
public ExtendedKuzzle(@NonNull String host, Options options, ResponseListener<Void> connectionCallback) throws URISyntaxException {
super(host, options, connectionCallback);
}
public ExtendedKuzzle(@NonNull String host) throws URISyntaxException {
super(host);
}
public ExtendedKuzzle(@NonNull String host, ResponseListener<Void> cb) throws URISyntaxException {
super(host, cb);
}
public ExtendedKuzzle(@NonNull String host, Options options) throws URISyntaxException {
super(host, options);
}
@Override
protected WebSocketClient createSocket() throws URISyntaxException {
WebSocketClient webSocketClient = super.createSocket();
try {
// SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
// sslContext.init(null, null, null);
webSocketClient.setSSLSocketFactory(new TLSSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
return webSocketClient;
}
}
public class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;
public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
internalSSLSocketFactory = context.getSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket());
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if(socket != null amp;amp; (socket instanceof SSLSocket)) {
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"});
// List<String> enabledProtocols = new ArrayList<>(Arrays.asList(((SSLSocket)socket).getEnabledProtocols()));
// if (enabledProtocols.size() > 1) {
// enabledProtocols.remove("SSLv3");
// ((SSLSocket)socket).setEnabledProtocols(enabledProtocols.toArray(new String[0]));
// }
}
return socket;
}
}
Я также безуспешно пытался установить «беспрекословный» TrustManager:
public static SSLSocketFactory createSslSocketFactory() throws Exception {
TrustManager[] byPassTrustManagers = new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
} };
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, byPassTrustManagers, new java.security.SecureRandom());
return sslContext.getSocketFactory();
}
Если кто-нибудь знает, что происходит, я был бы очень признателен. Большое спасибо!