Pregunta

Estoy usando ksoap2-android para hacer una llamada a un servicio WCF a través de SSL. Puedo conseguir que funcione sin SSL, pero ahora quiero hacer la llamada a través de SSL, pero me he encontrado a algunos problemas.

Estoy usando el HttpsTransportSE en lugar de HttpTransportSE, pero estoy consiguiendo el error: javax.net.ssl.SSLException: No es de confianza certificado de servidor

¿Cómo puedo solucionar este problema?

¿Puedo añadir el certificado de servidor en el almacén de claves en Android para resolver el 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;
}
¿Fue útil?

Solución

Bueno, hay una manera más fácil de hacer esto en lugar de modificar HttpsServiceConnectionSE. Puede instalar un gestor de confianza falsa como se describe en http://groups.google.com/group/android-developers/browse_thread/thread/1ac2b851e07269ba/c7275f3b28ad8bbc?lnk=gst&q=certificate y luego llamar allowAllSSL () antes de hacer cualquier comunicación SSL / llamada a ksoap2 . Se registrará un nuevo HostnameVerifier defecto y TrustManager. ksoap2, al hacer su comunicación SSL, utilizará la falta de pago y funciona como un encanto.

También puede poner un poco más esfuerzo en esto, lo hacen (mucho) más seguro, e instalar certificados en un gestor de confianza local de aplicación, supongo. Estaba en una red segura y no tiene miedo del hombre-en-medio-ataques por lo que acabo de hacer el primero.

He encontrado que es necesario utilizar KeepAliveHttpsTransportSE como esto new KeepAliveHttpsTransportSE(host, port, file, timeout);. Los parámetros van en un objeto URL, por lo que, por ejemplo, Para acceder a una instalación Jira es algo así como new KeepAliveHttpsTransportSE("host.whatever", 443, "/rpc/soap/jirasoapservice-v2", 1000).

A veces es útil si usted es nuevo en la tecnología o el servicio web que le gusta usar para jugar un rato con él en un entorno J2SE en lugar de en el emulador o incluso en el dispositivo, pero en el J2SE / ME ksoap2 la biblioteca (KeepAlive) HttpsTransportSE cosas es que falta (utilicé-2.1.2.jar ksoap2-j2se-completo). Lo que podría hacer es conseguir que las fuentes para las tres clases HttpsTransportSE, KeepAliveHttpsTransportSE y HttpsServiceConnectionSE desde el Android escisión ksoap2-androide y las puso en su proyecto de J2SE y usarlos. Se trabajó para mí y se convirtió en una mejora de la productividad para obtener los primeros pasos a la derecha con un desconocido y el servicio web bastante complejo.

Otros consejos

Para complementar la respuesta de Vedran con algo de código fuente, lo siento no puedo comentar.

El 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 llamada a su método:

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

Notas:

  1. Servidor es la dirección URL del servidor.
  2. 443 es el puerto por defecto https, que todavía tiene que especificar un puerto desde el constructor espera uno.
  3. URL de la ruta a la operación WS
  4. 1000 es el tiempo de espera

que se construye como: [Https: // servidor: 443 / URL]

funciona para mí WCF servicio 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 {

        }
    }

Sí, probablemente, se puede probar esto

conexión HTTPS Android

Se ha producido un error que ha sido presentada el control de incidencias con respecto a este

http://code.google.com/p/android / temas / detalle? id = 2388

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top