Question

J'utilise ksoap2-android pour faire un appel au service WCF sur SSL. Je peux le faire fonctionner sans SSL, mais maintenant je veux faire l'appel sur SSL, mais je n'ai plus pour certains problèmes.

J'utilise le HttpsTransportSE au lieu de HttpTransportSE, mais je reçois l'erreur: javax.net.ssl.SSLException: certificat de serveur non sécurisé

Comment puis-je résoudre ce problème?

Puis-je ajouter le certificat de serveur au Keystore dans Android pour résoudre le problème?

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;
}
Était-ce utile?

La solution

Eh bien, il est un moyen plus facile de le faire au lieu de modifier HttpsServiceConnectionSE. Vous pouvez installer un gestionnaire de confiance de faux comme décrit dans http://groups.google.com/group/android-developers/browse_thread/thread/1ac2b851e07269ba/c7275f3b28ad8bbc?lnk=gst&q=certificate puis appelez allowAllSSL () avant de faire une communication SSL / appel à ksoap2 . Il enregistrera une nouvelle valeur par défaut HostnameVerifier et TrustManager. ksoap2, lorsque vous faites sa communication SSL, utilisera ceux par défaut et il fonctionne comme un charme.

Vous pouvez aussi mettre un peu plus d'efforts dans ce, faire (beaucoup) plus sûr et installer des certificats dans une application gestionnaire de confiance local, je suppose. J'étais dans un réseau sûr et n'a pas peur de l'homme-in-the-middle-attaque donc je viens de faire le premier.

Je l'ai trouvé nécessaire d'utiliser KeepAliveHttpsTransportSE comme celui-ci new KeepAliveHttpsTransportSE(host, port, file, timeout);. Les paramètres entrent dans un objet URL, de sorte que par exemple d'accéder à une installation Jira, il est quelque chose comme new KeepAliveHttpsTransportSE("host.whatever", 443, "/rpc/soap/jirasoapservice-v2", 1000).

Parfois, il est à portée de main si vous êtes nouveau à la technologie ou le service Web que vous souhaitez utiliser pour jouer avec elle dans un environnement J2SE au lieu de l'émulateur ou même sur l'appareil, mais dans la bibliothèque J2SE / ME ksoap2 la (KeepAlive) manque des choses HttpsTransportSE (je ksoap2 J2SE plein-2.1.2.jar). Ce que vous pouvez faire est d'obtenir les sources pour les trois classes HttpsTransportSE, KeepAliveHttpsTransportSE et HttpsServiceConnectionSE de l'Android spin-off ksoap2-android et les mettre dans votre projet de J2SE et de les utiliser. Il a travaillé pour moi et il est devenu une amélioration de la productivité pour obtenir les premiers pas droit avec un inconnu et un service web assez complexe.

Autres conseils

Pour compléter la réponse de Vedran avec un code source, désolé, je ne peux pas commenter.

Le 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());
}

L'appel à votre méthode:

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

Notes:

  1. Server est l'URL du serveur.
  2. 443 est le port par défaut https, vous devez toujours spécifier un port depuis le constructeur attend un.
  3. URL le chemin de l'opération WS
  4. 1000 es le délai d'attente

Ce qui est construit comme: [Https: // serveur: 443 / URL]

Travaux pour moi KSOAP + WCF service Web avec Eclipse

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 {

        }
    }

Oui, vous pouvez probablement essayer cela

Https Connection Android

Il y a eu un bug qui a été déposée le problème Tracker au sujet de cette

http://code.google.com/p/android / questions / détail? id = 2388

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top