Domanda

sto usando ksoap2-Android per effettuare una chiamata al servizio WCF su SSL. Posso farlo funzionare senza SSL, ma ora voglio fare la chiamata su SSL, ma ho eseguito in alcuni problemi.

sto usando il HttpsTransportSE invece di HttpTransportSE, ma sto ottenendo l'errore: javax.net.ssl.SSLException: Non attendibile certificato server

Come posso risolvere questo problema?

Posso aggiungere il certificato del server al Keystore in Android per risolvere il problema?

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;
}
È stato utile?

Soluzione

Beh, c'è un modo più semplice per fare questo invece di modificare HttpsServiceConnectionSE. È possibile installare un gestore di falso fiducia come descritto in http://groups.google.com/group/android-developers/browse_thread/thread/1ac2b851e07269ba/c7275f3b28ad8bbc?lnk=gst&q=certificate e quindi chiamare allowAllSSL () prima di fare qualsiasi comunicazione SSL / chiamata a ksoap2 . Si registrerà un nuovo HostnameVerifier predefinito e TrustManager. ksoap2, quando si fa la comunicazione SSL, utilizzerà quelli di default e funziona come un fascino.

Si può anche mettere un po 'più sforzo in questo, ne fanno (molto) più sicuro e installare i certificati in un'applicazione direttore di fiducia locale, immagino. Ero in una rete sicura e non ha paura di man-in-the-middle attacchi così ho appena fatto la prima.

L'ho trovato necessario usare KeepAliveHttpsTransportSE come questo new KeepAliveHttpsTransportSE(host, port, file, timeout);. I parametri vanno in un oggetto URL, così ad esempio Per accedere a un'installazione Jira è qualcosa di simile new KeepAliveHttpsTransportSE("host.whatever", 443, "/rpc/soap/jirasoapservice-v2", 1000).

A volte è utile se siete nuovi alla tecnologia o il servizio web che si desidera utilizzare per giocare con essa in un ambiente J2SE, invece di nell'emulatore o anche sul dispositivo, ma nel J2SE / ME ksoap2 biblioteca (KeepAlive) HttpsTransportSE roba manca (io ho usato ksoap2-J2SE-full-2.1.2.jar). Che cosa si potrebbe fare è quello di ottenere i sorgenti per le tre classi HttpsTransportSE, KeepAliveHttpsTransportSE, e HttpsServiceConnectionSE dal Android spin-off ksoap2-android e metterli nel progetto J2SE e li usa. Ha funzionato per me e divenne un miglioramento della produttività per ottenere i primi passi a destra con uno sconosciuto e il servizio web abbastanza complesso.

Altri suggerimenti

Per completare la risposta di Vedran con un po 'di codice sorgente, mi dispiace non posso commentare.

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

La chiamata al tuo metodo:

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

Note:

  1. Server è l'URL del server.
  2. 443 è la porta predefinita https, si devono ancora specificare una porta in quanto il costruttore si aspetta uno.
  3. URL il percorso per l'operazione WS
  4. 1000 ES il timeout

che è costruito come: [Https: // server: 443 / URL]

Opere per me WCF servizio KSOAP + Web con 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 {

        }
    }

Si, probabilmente si può provare questo fuori

connessione HTTPS Android

C'è stato un bug che è stato depositato l'issue tracker per quanto riguarda questo

http://code.google.com/p/android / temi / dettaglio? id = 2388

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top