KSOAP 2 Android с HTTPS
Я использую KSOAP2 для управления SOAP в Android, но он использует https для URL-адреса SOAP, и я получаю эту ошибку: javax.net.ssl.SSLException: сертификат не доверенного сервера
Обычная ошибка, потому что сертификат не доверен, но кто знает, как обходиться с этой ошибкой?
Я не могу управлять сертификатом, потому что он из другой компании, и у меня нет доступа к его изменению.
Спасибо
Ответы
Ответ 1
Я еще не могу прокомментировать, поэтому я публикую свои комментарии для ответа на rallat. Его решение работает, но ему нужны дополнительные объяснения. Чтобы запустить ksoap2 с помощью ssl:
- Поместите
ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar
в проект
- Загрузите источники ksoap2 из https://github.com/mosabua/ksoap2-android/tree/ (репозиторий ksoap2)
- Скопировать
HttpTransportSE.java
, ServiceConnectionSE.java
(мне также нужно было скопировать Transport.java
, ServiceConnection.java
и HeaderProperty.java
). Удалите импорт из этих файлов и убедитесь, что они используют ваши файлы (а не импорт из ksoap2.jar
)
-
Использовать ответ rallat (я скопировал его):
-
ServiceConnectionSE.java
добавьте это для принятия ненадежного сертификата:
private TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
-
затем используйте эти конструкторы для
разрешить ненадежные сертификаты, а не
проверенные имена хостов:
public ServiceConnectionSE(String url) throws IOException {
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.getMessage();
}
connection = (HttpsURLConnection) new URL(url).openConnection();
((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());
}
-
Второй конструктор
public ServiceConnectionSE(Proxy proxy, String url) throws IOException {
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.getMessage();
}
connection = (HttpsURLConnection) new URL(url).openConnection();
((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());
connection.setUseCaches(false);
connection.setDoOutput(true);
connection.setDoInput(true);
}
-
В вашем коде просто используйте:
HttpTransportSE aht = new HttpTransportSE(URL);
aht.call(SOAP_ACTION, envelope);
Другие вещи, как в учебниках
Ответ 2
Проверяя снова эту проблему, я обнаружил для меня более чистое решение. Не требуется модификация файлов KSOAP2.
В своем проекте свяжите ksoap2-android-assembly-3.0.0-jar
без каких-либо изменений.
Затем создайте файл с именем SSLConnection.java
с помощью этого кода:
package com.example.mypackage;
import android.util.Log;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class SSLConection {
private static TrustManager[] trustManagers;
public static class _FakeX509TrustManager implements javax.net.ssl.X509TrustManager {
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return (_AcceptedIssuers);
}
}
public static void allowAllSSL() {
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
javax.net.ssl.SSLContext context;
if (trustManagers == null) {
trustManagers = new TrustManager[]{new _FakeX509TrustManager()};
}
try {
context = javax.net.ssl.SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
} catch (NoSuchAlgorithmException e) {
Log.e("allowAllSSL", e.toString());
} catch (KeyManagementException e) {
Log.e("allowAllSSL", e.toString());
}
}
}
И просто вызовите SSLConection.allowAllSSL();
перед вызовом метода сервера через KSOAP2. Все это работает для меня. Все SSL-сертификаты принимаются, и я могу использовать KSOAP2 с протоколом https.
Ответ 3
Я сам нахожу ответ
-
на ServiceConnectionSE.java добавьте это для получения сертификата с ненадежностью:
private TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
-
то в конструкторе добавьте это, чтобы разрешить ненадежные сертификаты и не проверенные имена хостов:
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.getMessage();
}
connection = (HttpsURLConnection) new URL(url).openConnection();
((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());
Ответ 4
Создайте новый класс FakeX509TrustManager, чтобы справиться с проблемой сертификата,
FakeX509TrustManager.allowAllSSL();
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
Новый созданный класс выглядит следующим образом:
public class FakeX509TrustManager implements X509TrustManager {
private static TrustManager[] trustManagers;
private static final X509Certificate[] _AcceptedIssuers = new
X509Certificate[] {};
@Override
public void checkClientTrusted(X509Certificate[] chain, String
authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String
authType) throws CertificateException {
}
public boolean isClientTrusted(X509Certificate[] chain) {
return true;
}
public boolean isServerTrusted(X509Certificate[] chain) {
return true;
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
public static void allowAllSSL() {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
{
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[] { new FakeX509TrustManager() };
}
try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
}
}