Ненадежный сертификат с использованием ksoap2-android - PullRequest
6 голосов
/ 10 января 2011

Я использую ksoap2-android для вызова сервиса wcf через SSL.Я могу заставить его работать без SSL, но теперь я хочу сделать вызов через SSL, но я столкнулся с некоторыми проблемами.

Я использую HttpsTransportSE вместо HttpTransportSE, но яПолучение ошибки: javax.net.ssl.SSLException: Ненадежный сертификат сервера

Как это исправить?

Можно ли добавить сертификат сервера в хранилище ключей в Android для решения проблемы?

private static final String SOAP_ACTION = "http://example.com/Service/GetInformation";
private static final String METHOD_NAME = "GetInformation";
private static final String NAMESPACE = "http://example.com";    
private static final String URL = "dev.example.com/Service.svc";

public static Result GetInformation()
{
    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

    PropertyInfo property = new PropertyInfo();
    property.name = "request";

    Request request =
        new Request("12", "13", "Ben");

    userInformationProperty.setValue(request);
    userInformationProperty.setType(request.getClass());
    request.addProperty(property);

    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.dotNet = true;
    envelope.setOutputSoapObject(request);
    envelope.addMapping(NAMESPACE, "Request",new Request().getClass());

    HttpsTransportSE transport = new HttpsTransportSE(URL, 443, "", 1000);

    //HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
    transport.debug = true;

    try
    {
        transport.call(SOAP_ACTION, envelope);          
        return Result.FromSoapResponse((SoapObject)envelope.getResponse());
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
    catch (XmlPullParserException e)
    {
        e.printStackTrace();
    }

    return null;
}

Ответы [ 4 ]

11 голосов
/ 03 августа 2012

Чтобы дополнить ответ Ведрана некоторым исходным кодом, извините, я не могу комментировать.

TrustManager:

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 boolean isClientTrusted(X509Certificate[] chain) {
        return (true);
    }

    public boolean isServerTrusted(X509Certificate[] chain) {
        return (true);
    }

    public X509Certificate[] getAcceptedIssuers() {
        return (_AcceptedIssuers);
    }
}

public static void allowAllSSL() {

    javax.net.ssl.HttpsURLConnection
            .setDefaultHostnameVerifier(new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });

    javax.net.ssl.SSLContext context = null;

    if (trustManagers == null) {
        trustManagers = new javax.net.ssl.TrustManager[] { new _FakeX509TrustManager() };
    }

    try {
        context = javax.net.ssl.SSLContext.getInstance("TLS");
        context.init(null, trustManagers, new SecureRandom());
    } catch (NoSuchAlgorithmException e) {
        Log.e("allowAllSSL", e.toString());
    } catch (KeyManagementException e) {
        Log.e("allowAllSSL", e.toString());
    }
    javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(context
            .getSocketFactory());
}

Звонок по вашему методу:

allowAllSSL();
HttpsTransportSE httpsTransport = new HttpsTransportSE(Server,443, URL, 1000);

Примечания:

  1. Сервер - это URL-адрес сервера.
  2. 443 - это порт https по умолчанию, вам все равно нужно указать порт, так как конструктор ожидает его.
  3. URL-адрес пути к операции WS
  4. 1000 по тайм-ауту

Который построен как: [https://Server:443/URL]

4 голосов
/ 24 января 2011

Ну, есть более простой способ сделать это вместо изменения HttpsServiceConnectionSE.Вы можете установить фальшивый менеджер доверия, как описано в http://groups.google.com/group/android-developers/browse_thread/thread/1ac2b851e07269ba/c7275f3b28ad8bbc?lnk=gst&q=certificate, а затем вызвать allowAllSSL (), прежде чем делать какие-либо SSL-соединения / вызов ksoap2.Он зарегистрирует новые значения по умолчанию HostnameVerifier и TrustManager.ksoap2 при использовании связи SSL будет использовать те, которые установлены по умолчанию, и работает как шарм.

Вы также можете приложить к этому дополнительные усилия, сделать его (намного) более безопасным и установить сертификаты в локальном приложениидоверительный управляющий, наверное.Я был в безопасной сети и не боялся атак типа «человек посередине», поэтому я просто выполнил первый.

Я счел необходимым использовать KeepAliveHttpsTransportSE, например, new KeepAliveHttpsTransportSE(host, port, file, timeout);.Параметры входят в объект URL, поэтому, например, для доступа к установке Jira это что-то вроде new KeepAliveHttpsTransportSE("host.whatever", 443, "/rpc/soap/jirasoapservice-v2", 1000).

Иногда это удобно, если вы новичок в этой технологии или в веб-сервисе, который вы хотели бы использовать для игры сэто в среде J2SE, а не в эмуляторе или даже на устройстве, но в библиотеке JsoSE / ME ksoap2 отсутствует (KeepAlive) HttpsTransportSE (я использовал ksoap2-j2se-full-2.1.2.jar).Что вы могли бы сделать, так это получить исходные коды для трех классов HttpsTransportSE, KeepAliveHttpsTransportSE и HttpsServiceConnectionSE из дополнительного продукта Android ksoap2-android, поместить их в свой проект J2SE и использовать их.Это сработало для меня, и стало повышением производительности, чтобы сделать первые шаги правильно с неизвестным и довольно сложным веб-сервисом.

1 голос
/ 11 апреля 2013

у меня работает KSOAP + веб-сервис WCF с затмением

private static SoapObject getBody(final SoapSerializationEnvelope soapEnvelope) throws Exception {
        if (soapEnvelope.bodyIn == null) {
            throw new Exception("soapEnvelope.bodyIn=null");
        }
        else if (soapEnvelope.bodyIn.getClass() == SoapFault.class) {
            throw new ExceptionLogic((SoapFault) soapEnvelope.bodyIn));
        }
        else {
            return (SoapObject) soapEnvelope.bodyIn;
        }

    }

private static SoapSerializationEnvelope sendRequete(final SoapObject soapReq, final String classMappingName,
            final Class<?> classMapping, final int timeOutSpecial) {



        final SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        soapEnvelope.implicitTypes = true;
        soapEnvelope.dotNet = true;

        if (classMappingName != null) {
            soapEnvelope.addMapping(NAMESPACE, classMappingName, classMapping);
        }

        soapEnvelope.setOutputSoapObject(soapReq);

        try {

            final HttpTransportSE httpTransport = new HttpTransportSE(Constante.urlWebService, timeOutSpecial);
            httpTransport.debug = BuildConfig.DEBUG;

            // Prod
            if (Constante.urlWebService.startsWith("https://")) {
                final List<HeaderProperty> headerList = new ArrayList<HeaderProperty>();
                headerList.add(new HeaderProperty("Authorization", "Basic "
                        + org.kobjects.base64.Base64.encode((Constante.CERTIFICAT_LOGIN + ":" + Constante.CERTIFICAT_MDP).getBytes())));

                FakeX509TrustManager.allowAllSSL();
                httpTransport.call(NAMESPACE + "/" + soapReq.getName(), soapEnvelope, headerList);
            }
            // Test
            else {
                httpTransport.call(NAMESPACE + "/" + soapReq.getName(), soapEnvelope);
            }

            return soapEnvelope;
        }
        catch (final Exception e) {
            throw new Exception("Erreur : " + e.getMessage(), e);
        }

    }



    private static class FakeX509TrustManager implements X509TrustManager {
        private static TrustManager[] trustManagers;
        private final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return _AcceptedIssuers;
        }

        public static void allowAllSSL() {
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

                @Override
                public boolean verify(final String hostname, final 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 (final NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            catch (final KeyManagementException e) {
                e.printStackTrace();
            }
            HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
        }

        @Override
        public void checkClientTrusted(final X509Certificate[] arg0, final String arg1) throws CertificateException {

        }

        @Override
        public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {

        }
    }
0 голосов
/ 10 января 2011

Да, вероятно, вы можете попробовать это

Https Connection Android

Произошла ошибка, которая была подана в систему отслеживания проблем в отношении этого

http://code.google.com/p/android/issues/detail?id=2388

...