wake-up-neo.net

HTTP-Verbindung Android

Ich mache einen https-Beitrag und erhalte eine Ausnahme von SSL-Ausnahme. Nicht vertrauenswürdiges Serverzertifikat. Wenn ich normales http mache, funktioniert es vollkommen in Ordnung. Muss ich das Serverzertifikat irgendwie akzeptieren?

97
Sam97305421562

Ich vermute, aber wenn Sie möchten, dass ein tatsächlicher Handshake durchgeführt wird, müssen Sie Android Ihr Zertifikat mitteilen. Wenn Sie einfach akzeptieren möchten, was auch immer ist, dann verwenden Sie diesen Pseudo-Code, um das zu bekommen, was Sie mit dem Apache HTTP-Client benötigen:

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 ist eine Klasse, die javax.net.ssl.X509TrustManager implementiert. Keine der Methoden führt jedoch tatsächlich irgendwelche Arbeit aus. Holen Sie sich ein Beispiel here .

Viel Glück!

45
Nate

Das mache ich. Das Zertifikat wird einfach nicht mehr geprüft.

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

und

    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();
    }
83
Ulrich Scheller

Beim Versuch, diese Frage zu beantworten, habe ich ein besseres Tutorial gefunden. Damit müssen Sie die Zertifikatprüfung nicht gefährden.

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

* Ich habe dies nicht geschrieben, aber danke an Bob Lee für die Arbeit

33
bajohns

Sie können sich auch meinen Blogartikel ansehen, der Crazybobs sehr ähnlich ist.

Diese Lösung beeinträchtigt auch nicht die Zertifikatprüfung und erläutert, wie vertrauenswürdige Zertifikate Ihrem eigenen Keystore hinzugefügt werden.

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

6
saxos

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

Mit freundlicher Genehmigung von Maduranga

Bei der Entwicklung einer Anwendung, die https verwendet, verfügt Ihr Testserver nicht über ein gültiges SSL-Zertifikat. Manchmal verwendet die Website ein selbstsigniertes Zertifikat oder die Website verwendet ein kostenloses SSL-Zertifikat. Wenn Sie also versuchen, mit Apache HttpClient eine Verbindung zum Server herzustellen, wird eine Ausnahme angezeigt, die besagt, dass der Peer nicht authentifiziert ist. Obwohl es nicht ratsam ist, allen Zertifikaten in einer Produktionssoftware zu vertrauen, müssen Sie dies je nach Situation tun. Diese Lösung behebt die durch "Peer nicht authentifiziert" verursachte Ausnahme.

Aber bevor wir zur Lösung gehen, muss ich Sie warnen, dass dies keine gute Idee für eine Produktionsanwendung ist. Dies verstößt gegen den Zweck der Verwendung eines Sicherheitszertifikats. Verwenden Sie diese Lösung nicht, es sei denn, Sie haben einen guten Grund oder Sie sind sich sicher, dass dies kein Problem verursacht.

Normalerweise erstellen Sie so ein HttpClient.

HttpClient httpclient = new DefaultHttpClient();

Sie müssen jedoch die Art und Weise ändern, in der Sie den HTTP-Client erstellen.

Zuerst müssen Sie eine Klasse mit der Erweiterung org.Apache.http.conn.ssl.SSLSocketFactory Erstellen.

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

Dann erstellen Sie eine solche Methode.

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

Dann können Sie das HttpClient erstellen.

HttpClient httpclient = getNewHttpClient();

Wenn Sie versuchen, eine Post-Anfrage an eine Anmeldeseite zu senden, sieht der Rest des Codes folgendermaßen aus.

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

Sie erhalten die HTML-Seite in den InputStream. Dann können Sie mit der zurückgegebenen HTML-Seite machen, was Sie wollen.

Aber hier werden Sie vor einem Problem stehen. Wenn Sie eine Sitzung mit Cookies verwalten möchten, können Sie dies mit dieser Methode nicht tun. Wenn Sie die Cookies erhalten möchten, müssen Sie dies über einen Browser tun. Dann erhalten nur Sie Cookies.

4
Rohit Mandiwal

Wenn Sie ein StartSSL- oder ein Thawte-Zertifikat verwenden, schlägt dies für Froyo und ältere Versionen fehl. Sie können ein neueres CAcert-Repository der Version verwenden, anstatt jedem Zertifikat zu vertrauen.

3
Juan Sánchez

Keines davon funktionierte für mich (verschlimmert durch den Thawte-Fehler ). Schließlich wurde es behoben mit Selbstsignierte SSL-Annahme unter Android und Benutzerdefinierte SSL-Verarbeitung funktioniert nicht mehr unter Android 2.2. FroYo

2
Adrian Spinei

Jede dieser Antworten hat für mich nicht funktioniert, also hier Code, der allen Zertifikaten vertraut.

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
Speise

Dies ist ein bekanntes Problem mit Android 2.x. Ich hatte eine Woche lang mit diesem Problem zu kämpfen, bis ich auf die folgende Frage stieß, die nicht nur einen guten Hintergrund des Problems bietet, sondern auch eine funktionierende und effektive Lösung ohne Sicherheitslücken bietet.

Fehler "Kein Peer-Zertifikat" in Android 2.3, aber NICHT in 4

1
alumat

Ich kenne die Android-Besonderheiten für SSL-Zertifikate nicht, aber es würde Sinn machen, dass Android ein selbstsigniertes SSL-Zertifikat nicht akzeptiert. Ich habe diesen Beitrag in Android-Foren gefunden, in denen das gleiche Problem zu behandeln ist: http://androidforums.com/Android-applications/950-imap-self-signed-ssl-certificates.html

1
Matti Lyra

Aus irgendeinem Grund hat die oben erwähnte Lösung für httpClient für mich nicht funktioniert. Am Ende konnte ich es funktionieren lassen, indem ich die Methode beim Implementieren der benutzerdefinierten SSLSocketFactory-Klasse korrekt überschriebe.

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

So hat es perfekt für mich funktioniert. Die vollständige benutzerdefinierte Klasse und Implementierung finden Sie im folgenden Thread: http://blog.syedgakbar.com/2012/07/21/Android-https-and-not-trusted-server-certificate-error/

0

Quellen, die mir geholfen haben, mit meinem selbstsignierten Zertifikat auf meinem AWS Apache-Server zu arbeiten und von Android-Gerät aus eine Verbindung mit HttpsURLConnection herzustellen:

SSL in einer aws-Instanz - Amazon-Tutorial zu SSL
Android-Sicherheit mit HTTPS und SSL - Erstellen eines eigenen Trust-Managers auf dem Client für die Annahme Ihres Zertifikats
Erstellen eines selbstsignierten Zertifikats - einfaches Skript zum Erstellen Ihrer Zertifikate

Dann habe ich folgendes gemacht:

  1. Stellen Sie sicher, dass der Server https unterstützt (Sudo yum install -y mod24_ssl).
  2. Legen Sie dieses Skript in eine Datei create_my_certs.sh:
#!/bin/bash
FQDN=$1

# 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. bash create_my_certs.sh yourdomain.com ausführen
  2. Platzieren Sie die Zertifikate an ihrem richtigen Platz auf dem Server (die Konfiguration finden Sie in /etc/httpd/conf.d/ssl.conf). Alle diese sollten festgelegt werden:
    SSLCertificateFile
    SSLCertificateKeyFile
    SSLCertificateChainFile
    SSLCACertificateFile

  3. Starten Sie httpd mit Sudo service httpd restart neu und stellen Sie sicher, dass httpd gestartet ist:
    Stoppen von httpd: [OK]
    Starten von httpd: [OK]

  4. Kopieren Sie my-private-root-ca.cert in Ihren Android-Projektordner

  5. Erstellen Sie Ihren Vertrauensmanager:

    SSLContext SSLContext;

    CertificateFactory cf = CertificateFactory.getInstance ("X.509"); InputStream caInput = context.getAssets (). Open ("my-private-root-ca.cert.pem"); Bescheinigung ca; Versuchen { ca = cf.generateCertificate (caInput); } endlich { caInput.close (); }

      // 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. Und stellen Sie die Verbindung mit HttpsURLConnection her:

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

  7. Versuchen Sie es mit Ihrer https-Verbindung.

0
MikeL

Ich mache diese Klasse und habe gefunden

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

in dir Code weiß das

CertificadoAceptar ca = new CertificadoAceptar();
ca.allowAllSSL();
HttpsTransportSE Transport = new HttpsTransportSE("iphost or Host name", 8080, "/WS/wsexample.asmx?WSDL", 30000);
0
Erick Guardado