Connexion Https Android

je fais un post https et j'obtiens une exception à l'exception de ssl pas de certificat de serveur de confiance. Si je fais un http normal, ça marche parfaitement. Dois-je accepter le certificat du serveur?

96
demandé sur Janusz 2009-06-15 15:02:20

14 réponses

je fais une supposition, mais si vous voulez qu'une vraie poignée de main se produise, vous devez en informer android de votre certificat. Si vous voulez simplement accepter quoi qu'il arrive, utilisez ce pseudo-code pour obtenir ce dont vous avez besoin avec le Client HTTP Apache:

SchemeRegistry schemeRegistry = new SchemeRegistry ();

schemeRegistry.register (new Scheme ("http",
    PlainSocketFactory.getSocketFactory (), 80));
schemeRegistry.register (new Scheme ("https",
    new CustomSSLSocketFactory (), 443));

ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager (
    params, schemeRegistry);


return new DefaultHttpClient (cm, params);

CustomSSLSocketFactory:

public class CustomSSLSocketFactory extends org.apache.http.conn.ssl.SSLSocketFactory
{
private SSLSocketFactory FACTORY = HttpsURLConnection.getDefaultSSLSocketFactory ();

public CustomSSLSocketFactory ()
    {
    super(null);
    try
        {
        SSLContext context = SSLContext.getInstance ("TLS");
        TrustManager[] tm = new TrustManager[] { new FullX509TrustManager () };
        context.init (null, tm, new SecureRandom ());

        FACTORY = context.getSocketFactory ();
        }
    catch (Exception e)
        {
        e.printStackTrace();
        }
    }

public Socket createSocket() throws IOException
{
    return FACTORY.createSocket();
}

 // TODO: add other methods like createSocket() and getDefaultCipherSuites().
 // Hint: they all just make a call to member FACTORY 
}

FullX509TrustManager est une classe qui implémente javax.net.ssl.X509TrustManager, pourtant aucune des méthodes n'effectue réellement un travail, obtenir un échantillon ici .

Bonne Chance!

45
répondu Nate 2011-05-26 12:52:58

C'est ce que je fais. Il ne vérifie plus le certificat.

// always verify the host - dont check for certificate
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};

/**
 * Trust every server - dont check for any certificate
 */
private static void trustAllHosts() {
    // Create a trust manager that does not validate certificate chains
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[] {};
        }

        public void checkClientTrusted(X509Certificate[] chain,
                String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain,
                String authType) throws CertificateException {
        }
    } };

    // Install the all-trusting trust manager
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection
                .setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

et

    HttpURLConnection http = null;

    if (url.getProtocol().toLowerCase().equals("https")) {
        trustAllHosts();
        HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
        https.setHostnameVerifier(DO_NOT_VERIFY);
        http = https;
    } else {
        http = (HttpURLConnection) url.openConnection();
    }
82
répondu Ulrich Scheller 2009-06-16 08:34:44

en essayant de répondre à cette question, j'ai trouvé un meilleur tutoriel. Avec elle, vous n'avez pas à compromettre la vérification du certificat.

http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

*je n'ai pas écrit cela, mais merci à Bob Lee pour le travail

33
répondu bajohns 2010-09-19 06:20:55

vous pouvez également regarder mon article de blog, très similaire à crazybobs.

cette solution ne compromet pas non plus la vérification des certificats et explique comment ajouter les certs de confiance dans votre propre keystore.

http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates /

6
répondu saxos 2011-03-06 18:01:38

http://madurangasblogs.blogspot.in/2013/08/avoiding-javaxnetsslsslpeerunverifiedex.html

Avec La Permission De Maduranga

lors du développement d'une application qui utilise https, votre serveur de test n'a pas de certificat SSL valide. Ou parfois le site web utilise un certificat auto-signé ou le site web utilise un certificat SSL gratuit. Donc, si vous essayez de vous connecter au serveur en utilisant Apache HttpClient , vous obtiendrez exception disant que le "pair non authentifié". Si elle n'est pas une bonne pratique de faire confiance à tous les certificats dans un logiciel de production, vous pouvez avoir à le faire selon la situation. Cette solution résout l'exception causée par "peer not authenticated".

Mais avant d'aller à la solution, je dois vous avertir que ce n'est pas une bonne idée pour une application de production. Ce sera atteinte à l'objet de l'aide d'un certificat de sécurité. Donc à moins que tu aies une bonne raison ou si vous êtes sûr que cela ne cause aucun problème, n'utilisez pas cette solution.

Normalement, vous créez un HttpClient comme ceci.

HttpClient httpclient = new DefaultHttpClient();

mais vous devez changer la façon dont vous créez le HttpClient.

vous devez d'abord créer une classe prolongeant org.apache.http.conn.ssl.SSLSocketFactory .

import org.apache.http.conn.ssl.SSLSocketFactory;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class MySSLSocketFactory extends SSLSocketFactory {
         SSLContext sslContext = SSLContext.getInstance("TLS");

    public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(truststore);

        TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

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

        sslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
}

alors créer une méthode comme celle-ci.

public HttpClient getNewHttpClient() {
     try {
         KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
         trustStore.load(null, null);

         SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
         sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

         HttpParams params = new BasicHttpParams();
         HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
         HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

         SchemeRegistry registry = new SchemeRegistry();
         registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
         registry.register(new Scheme("https", sf, 443));

         ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

         return new DefaultHttpClient(ccm, params);
     } catch (Exception e) {
         return new DefaultHttpClient();
     }
}

puis vous peut créer le HttpClient .

HttpClient httpclient = getNewHttpClient();

Si vous essayez d'envoyer une requête post vers une page de connexion le reste du code sera comme ceci.

private URI url = new URI("url of the action of the form");
HttpPost httppost =  new HttpPost(url);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();  
nameValuePairs.add(new BasicNameValuePair("username", "user"));  
nameValuePairs.add(new BasicNameValuePair("password", "password"));
try {
    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
    HttpResponse response = httpclient.execute(httppost);
    HttpEntity entity = response.getEntity();
    InputStream is = entity.getContent();
} catch (UnsupportedEncodingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (ClientProtocolException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

vous obtenez la page html à L'entrée. Ensuite, vous pouvez faire ce que vous voulez avec la page html retournée.

mais ici vous allez faire face à un problème. Si vous voulez gérer une session en utilisant des cookies, vous ne pourrez pas le faire avec ceci méthode. Si vous souhaitez obtenir les cookies, vous devrez le faire via un navigateur. Alors seulement vous recevrez des cookies.

5
répondu Rohit Mandiwal 2015-01-20 10:26:49

si vous utilisez un certificat StartSSL ou Thawte, il échouera pour Froyo et les versions plus anciennes. Vous pouvez utiliser une nouvelle version du dépôt CAcert au lieu de faire confiance à chaque certificat.

3
répondu Juan Sánchez 2013-09-19 15:44:18

aucun de ceux-ci n'a fonctionné pour moi (aggravé par le bug de dégel ainsi). Finalement je l'ai fait réparer avec acceptation SSL auto-signée sur Android et custom SSL handling stopped working on Android 2.2 FroYo

2
répondu Adrian Spinei 2017-05-23 12:02:29

toutes ces réponses n'ont pas fonctionné pour moi donc voici code qui font confiance à tous les certificats.

import java.io.IOException;

    import java.net.Socket;
    import java.security.KeyManagementException;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.UnrecoverableKeyException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;

    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;

    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.conn.scheme.PlainSocketFactory;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.conn.ssl.X509HostnameVerifier;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
    import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

    public class HttpsClientBuilder {
        public static DefaultHttpClient getBelieverHttpsClient() {

            DefaultHttpClient client = null;

            SchemeRegistry Current_Scheme = new SchemeRegistry();
            Current_Scheme.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            try {
                Current_Scheme.register(new Scheme("https", new Naive_SSLSocketFactory(), 8443));
            } catch (KeyManagementException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (UnrecoverableKeyException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (KeyStoreException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            HttpParams Current_Params = new BasicHttpParams();
            int timeoutConnection = 8000;
            HttpConnectionParams.setConnectionTimeout(Current_Params, timeoutConnection);
            int timeoutSocket = 10000;
            HttpConnectionParams.setSoTimeout(Current_Params, timeoutSocket);
            ThreadSafeClientConnManager Current_Manager = new ThreadSafeClientConnManager(Current_Params, Current_Scheme);
            client = new DefaultHttpClient(Current_Manager, Current_Params);
            //HttpPost httpPost = new HttpPost(url);
            //client.execute(httpPost);

         return client;
         }

    public static class Naive_SSLSocketFactory extends SSLSocketFactory
    {
        protected SSLContext Cur_SSL_Context = SSLContext.getInstance("TLS");

        public Naive_SSLSocketFactory ()
                throws NoSuchAlgorithmException, KeyManagementException,
                KeyStoreException, UnrecoverableKeyException
        {
            super(null, null, null, null, null, (X509HostnameVerifier)null);
            Cur_SSL_Context.init(null, new TrustManager[] { new X509_Trust_Manager() }, null);
        }

        @Override
        public Socket createSocket(Socket socket, String host, int port,
                boolean autoClose) throws IOException
        {
            return Cur_SSL_Context.getSocketFactory().createSocket(socket, host, port, autoClose);
        }

        @Override
        public Socket createSocket() throws IOException
        {
            return Cur_SSL_Context.getSocketFactory().createSocket();
        }
    }

    private static class X509_Trust_Manager implements X509TrustManager
    {

        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            // TODO Auto-generated method stub

        }

        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            // TODO Auto-generated method stub

        }

        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }

    };
}
2
répondu Speise 2012-10-05 08:41:27

Je ne sais pas quelles sont les spécificités D'Android pour les certificats ssl, mais il serait logique que Android n'accepte pas un certificat ssl auto-signé hors de question. J'ai trouvé ce post de forums android qui semble aborder le même problème: http://androidforums.com/android-applications/950-imap-self-signed-ssl-certificates.html

1
répondu Matti Lyra 2009-06-15 11:54:22

C'est un problème connu avec Android 2.x. J'ai été aux prises avec ce problème pendant une semaine jusqu'à ce que je tombe sur la question suivante, qui non seulement donne un bon arrière-plan du problème, mais fournit également une solution efficace et fonctionnelle sans trous de sécurité.

"pas d'erreur de certificat peer" dans Android 2.3 mais pas dans 4

1
répondu alumat 2017-05-23 11:46:55

pour une raison quelconque, la solution mentionnée pour httpClient ci-dessus n'a pas fonctionné pour moi. À la fin, j'ai pu le faire fonctionner en contournant correctement la méthode lors de la mise en œuvre de la classe custom SSLSocketFactory.

@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) 
                              throws IOException, UnknownHostException 
    {
    return sslFactory.createSocket(socket, host, port, autoClose);
}

@Override
public Socket createSocket() throws IOException {
    return sslFactory.createSocket();
}

C'est comme ça que ça a fonctionné parfaitement pour moi. Vous pouvez voir la classe personnalisée complète et l'implémentation sur le thread suivant: http://blog.syedgakbar.com/2012/07/21/android-https-and-not-trusted-server-certificate-error /

0
répondu Syed Ghulam Akbar 2012-07-23 06:19:40

je fais cette classe et j'ai trouvé

package com.example.fakessl;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;

import android.util.Log;

public class CertificadoAceptar {
    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());
    }
}

en code blanc ce

CertificadoAceptar ca = new CertificadoAceptar();
ca.allowAllSSL();
HttpsTransportSE Transport = new HttpsTransportSE("iphost or host name", 8080, "/WS/wsexample.asmx?WSDL", 30000);
0
répondu Erick Guardado 2014-01-20 23:00:16

Sources qui m'ont aidé à travailler avec mon certificat auto-signé sur mon serveur Apache AWS et me connecter avec HttpsURLConnection à partir de l'appareil android:



SSL sur AWS instance - amazon tutorial sur ssl

sécurité Android avec HTTPS et SSL - création de votre propre gestionnaire de confiance sur le client pour accepter votre certificat

création certificat auto-signé - script facile pour créer vos certificats

alors j'ai fait ce qui suit:

  1. S'est assuré que le serveur supporte https (sudo yum install-y mod24_ssl)
  2. mettez ce script dans un fichier create_my_certs.sh :
#!/bin/bash
FQDN=

# make directories to work from
mkdir -p server/ client/ all/

# Create your very own Root Certificate Authority
openssl genrsa \
  -out all/my-private-root-ca.privkey.pem \
  2048

# Self-sign your Root Certificate Authority
# Since this is private, the details can be as bogus as you like
openssl req \
  -x509 \
  -new \
  -nodes \
  -key all/my-private-root-ca.privkey.pem \
  -days 1024 \
  -out all/my-private-root-ca.cert.pem \
  -subj "/C=US/ST=Utah/L=Provo/O=ACME Signing Authority Inc/CN=example.com"

# Create a Device Certificate for each domain,
# such as example.com, *.example.com, awesome.example.com
# NOTE: You MUST match CN to the domain name or ip address you want to use
openssl genrsa \
  -out all/privkey.pem \
  2048

# Create a request from your Device, which your Root CA will sign
openssl req -new \
  -key all/privkey.pem \
  -out all/csr.pem \
  -subj "/C=US/ST=Utah/L=Provo/O=ACME Tech Inc/CN=${FQDN}"

# Sign the request from Device with your Root CA
openssl x509 \
  -req -in all/csr.pem \
  -CA all/my-private-root-ca.cert.pem \
  -CAkey all/my-private-root-ca.privkey.pem \
  -CAcreateserial \
  -out all/cert.pem \
  -days 500

# Put things in their proper place
rsync -a all/{privkey,cert}.pem server/
cat all/cert.pem > server/fullchain.pem         # we have no intermediates in this case
rsync -a all/my-private-root-ca.cert.pem server/
rsync -a all/my-private-root-ca.cert.pem client/
  1. Exécuter bash create_my_certs.sh yourdomain.com
  2. Place le certificats à leur place sur le serveur (vous pouvez trouver la configuration dans /etc/httpd/conf.d / ssl.conf). Tous ceux-ci doivent être mis:

    SSLCertificateFile

    SSLCertificateKeyFile
    151980920" SSLCertificateChainFile

    SSLCACertificateFile

  3. redémarrez httpd en utilisant sudo service httpd restart et assurez-vous que httpd démarre:

    L'arrêt de httpd: [ OK ]

    Démarrage de httpd: [OK ]

  4. Copie my-private-root-ca.cert de votre projet android actifs dossier

  5. Créer votre confiance manager:

    SSLContext SSLContext;

    CertificateFactory cf = CertificateFactory.getInstance ("X. 509"); InputStream caInput = cadre.getAssets ().open("mon-privé-root-ca.cert.pem"); Certificat ca; essayer { ca = cf.certificat général(caInput)); } enfin { caInput.proche(); }

      // Create a KeyStore containing our trusted CAs
      String keyStoreType = KeyStore.getDefaultType();
      KeyStore keyStore = KeyStore.getInstance(keyStoreType);
      keyStore.load(null, null);
      keyStore.setCertificateEntry("ca", ca);
    
      // Create a TrustManager that trusts the CAs in our KeyStore
      String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
      TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
      tmf.init(keyStore);
    
      // Create an SSLContext that uses our TrustManager
      SSLContext = SSLContext.getInstance("TLS");
      SSSLContext.init(null, tmf.getTrustManagers(), null);
    
  6. et faire la connexion en utilisant HttpsURLConnection:

    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connexion.setSSLSocketFactory (SSLContext.getSocketFactory());

  7. c'est ça, essayez votre connexion https.

0
répondu MikeL 2016-10-15 14:27:46

il suffit D'utiliser cette méthode comme votre HTTPClient:

public static  HttpClient getNewHttpClient() {
    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);

        SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DefaultHttpClient(ccm, params);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}
-1
répondu SerCna 2014-08-21 05:36:28