Vertrauen aller Zertifikate mit HttpClient über HTTPS

393

Kürzlich wurde eine Frage zu den HttpClientüber Https gestellt ( hier zu finden ). Ich habe einige Fortschritte gemacht, bin aber auf neue Probleme gestoßen. Wie bei meinem letzten Problem kann ich anscheinend nirgendwo ein Beispiel finden, das für mich funktioniert. Grundsätzlich möchte ich, dass mein Client jedes Zertifikat akzeptiert (weil ich immer nur auf einen Server zeige), aber ich bekomme immer einjavax.net.ssl.SSLException: Not trusted server certificate exception.

Das habe ich also:


    public void connect() throws A_WHOLE_BUNCH_OF_EXCEPTIONS {

        HttpPost post = new HttpPost(new URI(PROD_URL));
        post.setEntity(new StringEntity(BODY));

        KeyStore trusted = KeyStore.getInstance("BKS");
        trusted.load(null, "".toCharArray());
        SSLSocketFactory sslf = new SSLSocketFactory(trusted);
        sslf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme ("https", sslf, 443));
        SingleClientConnManager cm = new SingleClientConnManager(post.getParams(),
                schemeRegistry);

        HttpClient client = new DefaultHttpClient(cm, post.getParams());
        HttpResponse result = client.execute(post);
    }

Und hier ist der Fehler, den ich bekomme:

    W/System.err(  901): javax.net.ssl.SSLException: Not trusted server certificate 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:360) 
    W/System.err(  901):    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:321) 
    W/System.err(  901):    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:129) 
    W/System.err(  901):    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
    W/System.err(  901):    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
    W/System.err(  901):    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:129) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.access$0(MainActivity.java:77) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity$2.run(MainActivity.java:49) 
    W/System.err(  901): Caused by: java.security.cert.CertificateException: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:157) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:355) 
    W/System.err(  901):    ... 12 more 
    W/System.err(  901): Caused by: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty 
    W/System.err(  901):    at java.security.cert.PKIXParameters.checkTrustAnchors(PKIXParameters.java:645) 
    W/System.err(  901):    at java.security.cert.PKIXParameters.<init>(PKIXParameters.java:89) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.<init>(TrustManagerImpl.java:89) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl.engineGetTrustManagers(TrustManagerFactoryImpl.java:134) 
    W/System.err(  901):    at javax.net.ssl.TrustManagerFactory.getTrustManagers(TrustManagerFactory.java:226)W/System.err(  901):     at org.apache.http.conn.ssl.SSLSocketFactory.createTrustManagers(SSLSocketFactory.java:263) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:190) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:216) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:107) 
    W/System.err(  901):    ... 2 more
Harrisonlee
quelle
17
Ich musste dies für den internen Gebrauch tun. Ich hoffe wirklich, dass Sie nicht zulassen, dass Benutzer außerhalb Ihres Unternehmens Ihre App verwenden, da Sie sie für den Mann im mittleren Angriff geöffnet haben und sie dann für jemanden anfällig sind, der ihre Sitzung entführt. Trotzdem muss ich dies vorübergehend für einige Tests tun, bis ich das echte Zertifikat in der Hand habe ..... hoffentlich tun Sie es aus dem gleichen vorübergehenden Grund oder die App wird nur intern verwendet.
Dean Hiller
Ich habe diese Lösungen auf dem 4.3 Apache http Client ausprobiert, aber sie sind größtenteils veraltet. Hier ist keine veraltete Lösung: stackoverflow.com/a/18941950/2039471
Alexander Chzhen
Java 1.6 bietet keine SNI-Unterstützung, was auch in diesen Szenarien problematisch ist. Wenn Sie die Anforderung nicht ordnungsgemäß erstellen, erhalten Sie möglicherweise ein Zertifikat, das nicht mit der Anforderung übereinstimmt. Siehe Issues.apache.org/jira/browse/HTTPCLIENT-1119
Bron Davies
2
Diese Frage wird in der Zeitung The Most Dangerous Code in the World als Beispiel für trügerisches Denken angeführt. (Forschungsbericht: cs.utexas.edu/~shmat/shmat_ccs12.pdf )
mk_

Antworten:

421

Hinweis: Implementieren Sie dies nicht in Produktionscode, den Sie jemals in einem Netzwerk verwenden werden, dem Sie nicht vollständig vertrauen. Besonders alles, was über das öffentliche Internet geht.

Ihre Frage ist genau das, was ich wissen möchte. Nachdem ich einige Suchen durchgeführt habe, ist die Schlussfolgerung wie folgt.

Auf HttpClient-Weise sollten Sie eine benutzerdefinierte Klasse aus org.apache.http.conn.ssl.SSLSocketFactory erstellen, nicht aus der org.apache.http.conn.ssl.SSLSocketFactory selbst. Einige Hinweise finden Sie in diesem Beitrag. Die benutzerdefinierte SSL-Verarbeitung funktioniert unter Android 2.2 FroYo nicht mehr .

Ein Beispiel ist wie ...

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;

import org.apache.http.conn.ssl.SSLSocketFactory;
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();
    }
}

und verwenden Sie diese Klasse beim Erstellen einer Instanz von HttpClient.

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

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

Übrigens, der Link unten ist für jemanden, der nach einer HttpURLConnection-Lösung sucht. HTTP-Verbindung Android

Ich habe die beiden oben genannten Arten von Lösungen auf froyo getestet und sie funktionieren in meinen Fällen alle wie ein Zauber. Schließlich kann die Verwendung von HttpURLConnection zu Umleitungsproblemen führen, die jedoch über das Thema hinausgehen.

Hinweis: Bevor Sie sich entscheiden, allen Zertifikaten zu vertrauen, sollten Sie die Site wahrscheinlich genau kennen und für den Endbenutzer nicht schädlich sein.

In der Tat sollte das Risiko, das Sie eingehen, sorgfältig abgewogen werden, einschließlich der Auswirkungen der Hacker-Mock-Site, die in den folgenden Kommentaren erwähnt wird, die ich zutiefst schätze. In einigen Situationen, obwohl es schwierig sein kann, sich um alle Zertifikate zu kümmern, sollten Sie die impliziten Nachteile besser kennen, um allen zu vertrauen.

Daniel
quelle
150
Diese Antwort sollte wahrscheinlich beachten, dass das Vertrauen in alle Zertifikate schrecklich unsicher ist und den gesamten Zweck von ssl zunichte macht ...
yanokwa
22
@sweeney - Außer dass nicht garantiert ist, dass Sie mit dem Server sprechen, von dem Sie glauben, dass Sie es sind. Wenn jemand einen DNS-Server durcheinander gebracht hat, können Sie einen Verschlüsselungsschlüssel mit dem Server eines Hackers kommunizieren.
Richard Szalay
12
@sweeney Mit anderen Worten, Sie sind jetzt anfällig für Man-in-the-Middle-Angriffe. Sie sollten auch beachten, dass dieser Code nicht der Spezifikation entspricht: Überprüfen Sie das Javadoc. getAcceptedIssuers()darf nicht null zurückgeben.
Marquis von Lorne
25
-1 Weil es eine schreckliche Idee ist, alle Zertifikate zu akzeptieren. Es ist schade, dass es so viele Blogs und Tutorials gibt, die Java-Entwickler gerne auf dem Weg zum Falschen führen.
Tim Bender
57
+1 Weil ich eine schnelle Lösung nur für Debugging-Zwecke brauchte. Ich würde dies aus Sicherheitsgründen, die andere erwähnt haben, nicht in der Produktion verwenden, aber genau das brauchte ich zum Testen. Vielen Dank!
Danation
495

Grundsätzlich haben Sie vier mögliche Lösungen, um eine "Nicht vertrauenswürdige" Ausnahme unter Android mithilfe von httpclient zu beheben:

  1. Vertrauen Sie allen Zertifikaten. Tun Sie dies nicht, es sei denn, Sie wissen wirklich, was Sie tun.
  2. Erstellen Sie eine benutzerdefinierte SSLSocketFactory, die nur Ihrem Zertifikat vertraut. Dies funktioniert, solange Sie genau wissen, zu welchen Servern Sie eine Verbindung herstellen möchten. Sobald Sie jedoch eine Verbindung zu einem neuen Server mit einem anderen SSL-Zertifikat herstellen müssen, müssen Sie Ihre App aktualisieren.
  3. Erstellen Sie eine Keystore-Datei, die die "Master-Liste" der Zertifikate von Android enthält, und fügen Sie dann Ihre eigene hinzu. Wenn eines dieser Zertifikate später abläuft, sind Sie dafür verantwortlich, es in Ihrer App zu aktualisieren. Ich kann mir keinen Grund dafür vorstellen.
  4. Erstellen Sie eine benutzerdefinierte SSLSocketFactory, die das integrierte Zertifikat KeyStore verwendet, jedoch auf einen alternativen KeyStore zurückgreift, wenn alles nicht mit der Standardeinstellung überprüft werden kann.

Diese Antwort verwendet die Lösung Nr. 4, die mir am robustesten erscheint.

Die Lösung besteht darin, eine SSLSocketFactory zu verwenden, die mehrere KeyStores akzeptieren kann, sodass Sie Ihren eigenen KeyStore mit Ihren eigenen Zertifikaten versorgen können. Auf diese Weise können Sie zusätzliche Zertifikate der obersten Ebene wie Thawte laden, die auf einigen Android-Geräten möglicherweise fehlen. Außerdem können Sie Ihre eigenen selbstsignierten Zertifikate laden. Es werden zuerst die integrierten Standardgerätezertifikate verwendet und nur bei Bedarf auf Ihre zusätzlichen Zertifikate zurückgegriffen.

Zunächst möchten Sie feststellen, welches Zertifikat in Ihrem KeyStore fehlt. Führen Sie den folgenden Befehl aus:

openssl s_client -connect www.yourserver.com:443

Und Sie sehen die Ausgabe wie folgt:

Certificate chain
 0 s:/O=www.yourserver.com/OU=Go to 
   https://www.thawte.com/repository/index.html/OU=Thawte SSL123 
   certificate/OU=Domain Validated/CN=www.yourserver.com
   i:/C=US/O=Thawte, Inc./OU=Domain Validated SSL/CN=Thawte DV SSL CA
 1 s:/C=US/O=Thawte, Inc./OU=Domain Validated SSL/CN=Thawte DV SSL CA
   i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 
   2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA

Wie Sie sehen, stammt unser Stammzertifikat von Thawte. Gehen Sie zur Website Ihres Anbieters und suchen Sie das entsprechende Zertifikat. Für uns war es hier und Sie können sehen, dass das, was wir brauchten, das Copyright 2006 war.

Wenn Sie ein selbstsigniertes Zertifikat verwenden, mussten Sie den vorherigen Schritt nicht ausführen, da Sie bereits über Ihr Signaturzertifikat verfügen.

Erstellen Sie dann eine Keystore-Datei mit dem fehlenden Signaturzertifikat. Crazybob hat Details dazu auf Android , aber die Idee ist, Folgendes zu tun:

Wenn Sie es noch nicht haben, laden Sie die Bouncy Castle Provider-Bibliothek von folgender Adresse herunter: http://www.bouncycastle.org/latest_releases.html . Dies wird auf Ihrem Klassenpfad unten gehen.

Führen Sie einen Befehl aus, um das Zertifikat vom Server zu extrahieren und eine PEM-Datei zu erstellen. In diesem Fall mycert.pem.

echo | openssl s_client -connect ${MY_SERVER}:443 2>&1 | \
 sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > mycert.pem

Führen Sie dann die folgenden Befehle aus, um den Schlüsselspeicher zu erstellen.

export CLASSPATH=/path/to/bouncycastle/bcprov-jdk15on-155.jar
CERTSTORE=res/raw/mystore.bks
if [ -a $CERTSTORE ]; then
    rm $CERTSTORE || exit 1
fi
keytool \
      -import \
      -v \
      -trustcacerts \
      -alias 0 \
      -file <(openssl x509 -in mycert.pem) \
      -keystore $CERTSTORE \
      -storetype BKS \
      -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
      -providerpath /path/to/bouncycastle/bcprov-jdk15on-155.jar \
      -storepass some-password

Sie werden feststellen, dass das obige Skript das Ergebnis in platziert res/raw/mystore.bks. Jetzt haben Sie eine Datei, die Sie in Ihre Android-App laden und die fehlenden Zertifikate bereitstellen.

Registrieren Sie dazu Ihre SSLSocketFactory für das SSL-Schema:

final SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", createAdditionalCertsSSLSocketFactory(), 443));

// and then however you create your connection manager, I use ThreadSafeClientConnManager
final HttpParams params = new BasicHttpParams();
...
final ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params,schemeRegistry);

So erstellen Sie Ihre SSLSocketFactory:

protected org.apache.http.conn.ssl.SSLSocketFactory createAdditionalCertsSSLSocketFactory() {
    try {
        final KeyStore ks = KeyStore.getInstance("BKS");

        // the bks file we generated above
        final InputStream in = context.getResources().openRawResource( R.raw.mystore);  
        try {
            // don't forget to put the password used above in strings.xml/mystore_password
            ks.load(in, context.getString( R.string.mystore_password ).toCharArray());
        } finally {
            in.close();
        }

        return new AdditionalKeyStoresSSLSocketFactory(ks);

    } catch( Exception e ) {
        throw new RuntimeException(e);
    }
}

Und schließlich der AdditionalKeyStoresSSLSocketFactory-Code, der Ihren neuen KeyStore akzeptiert und prüft, ob der integrierte KeyStore ein SSL-Zertifikat nicht validieren kann:

/**
 * Allows you to trust certificates from additional KeyStores in addition to
 * the default KeyStore
 */
public class AdditionalKeyStoresSSLSocketFactory extends SSLSocketFactory {
    protected SSLContext sslContext = SSLContext.getInstance("TLS");

    public AdditionalKeyStoresSSLSocketFactory(KeyStore keyStore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(null, null, null, null, null, null);
        sslContext.init(null, new TrustManager[]{new AdditionalKeyStoresTrustManager(keyStore)}, null);
    }

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

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



    /**
     * Based on http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#X509TrustManager
     */
    public static class AdditionalKeyStoresTrustManager implements X509TrustManager {

        protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>();


        protected AdditionalKeyStoresTrustManager(KeyStore... additionalkeyStores) {
            final ArrayList<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>();

            try {
                // The default Trustmanager with default keystore
                final TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                original.init((KeyStore) null);
                factories.add(original);

                for( KeyStore keyStore : additionalkeyStores ) {
                    final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                    additionalCerts.init(keyStore);
                    factories.add(additionalCerts);
                }

            } catch (Exception e) {
                throw new RuntimeException(e);
            }



            /*
             * Iterate over the returned trustmanagers, and hold on
             * to any that are X509TrustManagers
             */
            for (TrustManagerFactory tmf : factories)
                for( TrustManager tm : tmf.getTrustManagers() )
                    if (tm instanceof X509TrustManager)
                        x509TrustManagers.add( (X509TrustManager)tm );


            if( x509TrustManagers.size()==0 )
                throw new RuntimeException("Couldn't find any X509TrustManagers");

        }

        /*
         * Delegate to the default trust manager.
         */
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            final X509TrustManager defaultX509TrustManager = x509TrustManagers.get(0);
            defaultX509TrustManager.checkClientTrusted(chain, authType);
        }

        /*
         * Loop over the trustmanagers until we find one that accepts our server
         */
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            for( X509TrustManager tm : x509TrustManagers ) {
                try {
                    tm.checkServerTrusted(chain,authType);
                    return;
                } catch( CertificateException e ) {
                    // ignore
                }
            }
            throw new CertificateException();
        }

        public X509Certificate[] getAcceptedIssuers() {
            final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();
            for( X509TrustManager tm : x509TrustManagers )
                list.addAll(Arrays.asList(tm.getAcceptedIssuers()));
            return list.toArray(new X509Certificate[list.size()]);
        }
    }

}
emmby
quelle
Hey @emmby, dies scheint die perfekte Antwort für mein Problem zu sein, aber ich bekomme immer noch keine SSL-Verbindung. Können Sie es sich bitte ansehen? http://stackoverflow.com/questions/7822381/need-help-understanding-certificate-chains
Matthias B
Danke für das tolle Schreiben @emmby! Ich bekomme manchmal eine sehr lange Verzögerung und dann eine javax.net.ssl.SSLException: Lesefehler:. Irgendeine Idee? Wie kann ich ein Timeout festlegen, wenn die Lösung mit stackoverflow.com/questions/5909308/android-2-3-4-ssl-problem identisch ist ?
Edwin Evans
3
@emmby, können Sie sagen, wo ich diesen Code ablegen soll? export CLASSPATH = bcprov-jdk16-145.jar CERTSTORE = res / raw / mystore.bks if [-a $ CERTSTORE]; dann rm $ CERTSTORE || Beenden Sie 1 fi keytool \ -import \ -v \ -trustcacerts \ -alias 0 \ -file <(openssl x509 -in mycert.pem) \ -keystore $ CERTSTORE \ -storetype BKS \ -provider org.bouncycastle.jce.provider. BouncyCastleProvider \ -providerpath /usr/share/java/bcprov.jar \ -storepass some-password
Rikki Tikki Tavi
1
Hey @emmby. Ich verwende Ihre Lösung in meiner App und verwende ein selbstsigniertes Zertifikat meines Servers, erhalte jedoch eine CertificateException () in der checkServerTrusted () -Methode. Ich habe versucht, diese Wurfausnahme zu kommentieren, und sie funktioniert. Wenn mein Serverzertifikat nicht validiert wird, kann ich es dann anders behandeln. Können Sie bitte angeben, welche Lösung in diesem Fall die beste ist?
Ankit
7
Dies sollte als die richtige Antwort markiert werden. Eine der gründlichsten und am besten geschriebenen Antworten, die ich je auf SO gesehen habe. Dope
Kachi
74

Fügen Sie diesen Code vor dem hinzu HttpsURLConnectionund es wird getan. Ich habe es bekommen.

private void trustEveryone() { 
    try { 
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){ 
                    public boolean verify(String hostname, SSLSession session) { 
                            return true; 
                    }}); 
            SSLContext context = SSLContext.getInstance("TLS"); 
            context.init(null, new X509TrustManager[]{new X509TrustManager(){ 
                    public void checkClientTrusted(X509Certificate[] chain, 
                                    String authType) throws CertificateException {} 
                    public void checkServerTrusted(X509Certificate[] chain, 
                                    String authType) throws CertificateException {} 
                    public X509Certificate[] getAcceptedIssuers() { 
                            return new X509Certificate[0]; 
                    }}}, new SecureRandom()); 
            HttpsURLConnection.setDefaultSSLSocketFactory( 
                            context.getSocketFactory()); 
    } catch (Exception e) { // should never happen 
            e.printStackTrace(); 
    } 
} 

Ich hoffe das hilft dir.

Alok Gupta
quelle
22
Siehe die obigen Ausführungen unter der akzeptierten Antwort. Diese "Lösung" ist radikal unsicher.
Marquis von Lorne
5
Dies ist die ideale Q & D-Lösung. Kurz und "funktioniert einfach".
Steve Smith
5
Perfekte Antwort zu Testzwecken !!! Und ja, es ist eine schlechte Idee, sie in der Produktion zu verwenden, aber komm schon ... das sollte jedem klar sein, der sich den Fragentitel ansieht. Es beantwortet es immer noch am besten / kürzesten / mit der gleichen (In-) Sicherheitsstufe!
Levit
34

Das ist eine schlechte Idee. Das Vertrauen in ein Zertifikat ist nur (sehr) geringfügig besser als die Verwendung von überhaupt keinem SSL. Wenn Sie sagen "Ich möchte, dass mein Client ein Zertifikat akzeptiert (weil ich immer nur auf einen Server zeige)", gehen Sie davon aus, dass das Zeigen auf "einen Server" sicher ist, was nicht in einem öffentlichen Netzwerk der Fall ist.

Sie sind völlig offen für einen Man-in-the-Middle-Angriff, indem Sie einem Zertifikat vertrauen. Jeder kann Ihre Verbindung vertreten, indem er eine separate SSL-Verbindung mit Ihnen und dem Endserver herstellt. Das MITM hat dann Zugriff auf Ihre gesamte Anfrage und Antwort. Sofern Sie SSL überhaupt nicht benötigt haben (Ihre Nachricht ist nicht vertraulich und führt keine Authentifizierung durch), sollten Sie nicht allen Zertifikaten blind vertrauen.

Sie sollten in Betracht ziehen, das öffentliche Zertifikat mithilfe von Keytool zu einem JKS hinzuzufügen und dieses zum Erstellen Ihrer Socket-Factory zu verwenden, z.

    KeyStore ks = KeyStore.getInstance("JKS");

    // get user password and file input stream
    char[] password = ("mykspassword")).toCharArray();
    ClassLoader cl = this.getClass().getClassLoader();
    InputStream stream = cl.getResourceAsStream("myjks.jks");
    ks.load(stream, password);
    stream.close();

    SSLContext sc = SSLContext.getInstance("TLS");
    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
    TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

    kmf.init(ks, password);
    tmf.init(ks);

    sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),null);

    return sc.getSocketFactory();

Dies hat eine Einschränkung zu beachten. Das Zertifikat läuft irgendwann ab und der Code funktioniert zu diesem Zeitpunkt nicht mehr. Sie können leicht feststellen, wann dies geschehen wird, indem Sie sich das Zertifikat ansehen.

Dan
quelle
5
Wenn Sie auf Client-Seite keine Clientzertifikatauthentifizierung verwenden, benötigen Sie keinen Schlüsselmanager ( nullin SSLContext.init). You should also use the default algorithms (KMF/TMF.getDefaultAlgorithm() ), instead of hard-coding SunX509 verwenden` (mehr noch, da der Standard für TMF tatsächlich PKIXauf der Sun / Oracle-JVM liegt).
Bruno
Gibt es eine gebrauchsfertige Stammzertifikatsdatei? (wie Browser)
Dani Herrera
Woher myjks.jkskommt das?
Zionpi
1
@zionpi Generiert mit Java "keytool".
Dan
22

Sie können die HttpURLConnection-SSL-Prüfung zu Testzwecken auf diese Weise deaktivieren, da API 8:

    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    if (conn instanceof HttpsURLConnection) {
        HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
        httpsConn.setSSLSocketFactory(SSLCertificateSocketFactory.getInsecure(0, null));
        httpsConn.setHostnameVerifier(new AllowAllHostnameVerifier());
    }
hfmanson
quelle
2
org.apache.http.conn.ssl.AllowAllHostnameVerifierist veraltet.
Zackygaurav
2
@zackygaurav Nach dem javadoc , AllowAllHostnameVerifierwird ersetzt durch NoopHostnameVerifier"
DLight
10

Die API von HttpComponents wurde geändert. Es funktioniert mit dem folgenden Code.

public static HttpClient getTestHttpClient() {
    try {
        SSLSocketFactory sf = new SSLSocketFactory(new TrustStrategy(){
            @Override
            public boolean isTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
                return true;
            }
        }, new AllowAllHostnameVerifier());

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("https",8444, sf));
        ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry);
        return new DefaultHttpClient(ccm);
    } catch (Exception e) {
        e.printStackTrace();
        return new DefaultHttpClient();
    }
}
Prabhu Periasamy
quelle
Die Verwendung einer benutzerdefinierten Vertrauensstrategie ist die richtige Antwort. Vielen Dank.
Matt Friedman
10

Der obige Code unter https://stackoverflow.com/a/6378872/1553004 ist korrekt, außer dass er auch den Hostnamen-Verifizierer aufrufen muss:

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

Ich habe mich ausdrücklich bei stackoverflow angemeldet, um dieses Update hinzuzufügen. Beachten Sie meine Warnung!

Robert Blair
quelle
Was tun Sie mit nachfolgenden Verbindungen, wenn Sie das Zertifikat bei der ersten Verbindung auf diese Weise überprüft haben? Nutzen Sie das Wissen, das Sie aus der ersten Verbindung gewonnen haben? Was ist, wenn bei Verbindungsversuch 3 ein gefälschtes Zertifikat mit demselben Namen verwendet wird?
JWW
6

Ich füge eine Antwort für diejenigen hinzu, die httpclient-4.5 verwenden, und funktioniert wahrscheinlich auch für 4.4.

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.fluent.ContentResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;



public class HttpClientUtils{

public static HttpClient getHttpClientWithoutSslValidation_UsingHttpClient_4_5_2() {
    try {
        SSLContextBuilder builder = new SSLContextBuilder();
        builder.loadTrustMaterial(null, new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        });
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), new NoopHostnameVerifier());
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); 
        return httpclient;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
}
Rosercostin
quelle
Was ist die neue NoopHostnameVerifier () -Klasse?
Mushtakim Ahmed Ansari
1
@MushtakimAhmedAnsari Aus den Dokumenten: "Der NO_OP HostnameVerifier deaktiviert im Wesentlichen die Überprüfung des Hostnamens. Diese Implementierung ist ein No-Op und löst niemals die SSLException aus."
Rosercostin
Vielen Dank für die tolle Antwort. Dieser sollte mehr Stimmen bekommen.
Abhay Dwivedi
Wie benutze ich es? oder schlagen Sie vor, dass die einfache Überprüfung der Klasse die Überprüfung von SSL-Zertifikaten außer Kraft setzt?
siehe
Ja. dass httpClient bei Verwendung keine https-Zertifikate validiert
raisercostin
4

Das Vertrauen in alle Zertifikate war für mich keine echte Alternative. Daher habe ich Folgendes getan, um HttpsURLConnection dazu zu bringen, einem neuen Zertifikat zu vertrauen (siehe auch http://nelenkov.blogspot.jp/2011/12/using-custom-certificate-trust-store- on.html ).

  1. Holen Sie sich das Zertifikat; Dazu habe ich das Zertifikat in Firefox exportiert (auf das kleine Schlosssymbol klicken, Zertifikatdetails abrufen, auf Exportieren klicken) und dann mit portecle einen Truststore (BKS) exportiert.

  2. Laden Sie den Truststore aus /res/raw/geotrust_cert.bks mit dem folgenden Code:

        final KeyStore trustStore = KeyStore.getInstance("BKS");
        final InputStream in = context.getResources().openRawResource(
                R.raw.geotrust_cert);
        trustStore.load(in, null);
    
        final TrustManagerFactory tmf = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);
    
        final SSLContext sslCtx = SSLContext.getInstance("TLS");
        sslCtx.init(null, tmf.getTrustManagers(),
                new java.security.SecureRandom());
    
        HttpsURLConnection.setDefaultSSLSocketFactory(sslCtx
                .getSocketFactory());
koljaTM
quelle
Ich bekomme diesen Fehler. IOExceptionjavax.net.ssl.SSLPeerUnverifiedException: No peer certificate. Dies, wenn der eigentliche Ausführungsaufruf auf dem HttpClient ausgeführt wird, nachdem das obige Setup durchgeführt wurde.
Michael
3

Hier ist eine sehr einfache Version mit 4.1.2 httpclient-Code. Dies kann dann an einen beliebigen Vertrauensalgorithmus angepasst werden, den Sie für richtig halten.

public static HttpClient getTestHttpClient() {
    try {
        SSLSocketFactory sf = new SSLSocketFactory(new TrustStrategy(){
            @Override
            public boolean isTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
                return true;
            }
        });
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("https", 443, sf));
        ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry);
        return new DefaultHttpClient(ccm);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}
Joseph Valerio
quelle
3

Ich habe eine Antwort von "emmby" (beantwortet am 16. Juni 11 um 21:29 Uhr), Punkt 4: "Erstellen Sie eine benutzerdefinierte SSLSocketFactory, die das integrierte Zertifikat KeyStore verwendet, aber für alles, was fehlschlägt, auf einen alternativen KeyStore zurückgreift mit der Standardeinstellung zu überprüfen. "

Dies ist eine vereinfachte Implementierung. Laden Sie den Systemschlüsselspeicher und führen Sie ihn mit dem Anwendungsschlüsselspeicher zusammen.

public HttpClient getNewHttpClient() {
    try {
        InputStream in = null;
        // Load default system keystore
        KeyStore trusted = KeyStore.getInstance(KeyStore.getDefaultType()); 
        try {
            in = new BufferedInputStream(new FileInputStream(System.getProperty("javax.net.ssl.trustStore"))); // Normally: "/system/etc/security/cacerts.bks"
            trusted.load(in, null); // no password is "changeit"
        } finally {
            if (in != null) {
                in.close();
                in = null;
            }
        }

        // Load application keystore & merge with system
        try {
            KeyStore appTrusted = KeyStore.getInstance("BKS"); 
            in = context.getResources().openRawResource(R.raw.mykeystore);
            appTrusted.load(in, null); // no password is "changeit"
            for (Enumeration<String> e = appTrusted.aliases(); e.hasMoreElements();) {
                final String alias = e.nextElement();
                final KeyStore.Entry entry = appTrusted.getEntry(alias, null);
                trusted.setEntry(System.currentTimeMillis() + ":" + alias, entry, null);
            }
        } finally {
            if (in != null) {
                in.close();
                in = null;
            }
        }

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

        SSLSocketFactory sf = new SSLSocketFactory(trusted);
        sf.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

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

Ein einfacher Modus zum Konvertieren von JKS in BKS:

keytool -importkeystore -destkeystore cacerts.bks -deststoretype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk16-141.jar -deststorepass changeit -srcstorepass changeit -srckeystore $JAVA_HOME/jre/lib/security/cacerts -srcstoretype JKS -noprompt

* Hinweis: In Android 4.0 (ICS) hat sich der Trust Store geändert. Weitere Informationen: http://nelenkov.blogspot.com.es/2011/12/ics-trust-store-implementation.html

ggrandes
quelle
3

Gehen Sie folgendermaßen vor, wenn Sie möchten, dass alle Zertifikate (zu Testzwecken) über OAuth funktionieren:

1) Laden Sie hier den Quellcode der Android OAuth API herunter: https://github.com/kaeppler/signpost

2) Suchen Sie die Klasse "CommonsHttpOAuthProvider"

3) Ändern Sie es wie folgt:

public class CommonsHttpOAuthProvider extends AbstractOAuthProvider {

private static final long serialVersionUID = 1L;

private transient HttpClient httpClient;

public CommonsHttpOAuthProvider(String requestTokenEndpointUrl, String accessTokenEndpointUrl,
        String authorizationWebsiteUrl) {
    super(requestTokenEndpointUrl, accessTokenEndpointUrl, authorizationWebsiteUrl);


    //this.httpClient = new DefaultHttpClient();//Version implemented and that throws the famous "javax.net.ssl.SSLException: Not trusted server certificate" if the certificate is not signed with a CA
    this.httpClient = MySSLSocketFactory.getNewHttpClient();//This will work with all certificates (for testing purposes only)
}

Die obige "MySSLSocketFactory" basiert auf der akzeptierten Antwort. Um es noch einfacher zu machen, folgt hier die komplette Klasse:

package com.netcomps.oauth_example;

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;

import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
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.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;

//http://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https
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() {

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

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

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



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

}}

Hoffe das hilft jemandem.

Tiago
quelle
1
Die Frage war HttpClientund HTTPS; nicht OAuth für Android aus einem GitHub-Projekt.
JWW
3

Ich habe dies verwendet und es funktioniert für mich auf allen Betriebssystemen.

/**
 * Disables the SSL certificate checking for new instances of {@link HttpsURLConnection} This has been created to
 * aid testing on a local box, not for use on production.
 */


private static void disableSSLCertificateChecking() {
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            // Not implemented
        }

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            // Not implemented
        }
    } };

    try {
        SSLContext sc = SSLContext.getInstance("TLS");

        sc.init(null, trustAllCerts, new java.security.SecureRandom());

        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}
Baiju Sharma
quelle
Hallo @ yegor256, ich verwende diesen Code, bekomme aber immer noch ein SSL-Handshake-Problem
user2028
1

Nur das Hinzufügen -Dtrust_all_cert=truezu VM-Argumenten sollte ausreichen. Dieses Argument weist Java an, Zertifikatprüfungen zu ignorieren.

Ayman Hussain
quelle
4
Bitte fügen Sie nicht dieselbe Antwort auf mehrere Fragen hinzu. Beantworten Sie die beste Frage und markieren Sie den Rest als Duplikate. Siehe Ist es akzeptabel, mehrere Fragen doppelt zu beantworten?
Petter Friberg
0

Jeder Körper, der immer noch mit StartCom SSL-Zertifikaten unter Android 2.1 zu kämpfen hat, besucht https://www.startssl.com/certs/ und lädt das ca.pem herunter, jetzt in der Antwort von @emmby replace

`export CLASSPATH=bcprov-jdk16-145.jar
 CERTSTORE=res/raw/mystore.bks
      if [ -a $CERTSTORE ]; then
          rm $CERTSTORE || exit 1
      fi
 keytool \
  -import \
  -v \
  -trustcacerts \
  -alias 0 \
  -file <(openssl x509 -in mycert.pem) \
  -keystore $CERTSTORE \
  -storetype BKS \
  -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
  -providerpath /usr/share/java/bcprov.jar \
  -storepass some-password`

mit

 `export CLASSPATH=bcprov-jdk16-145.jar
 CERTSTORE=res/raw/mystore.bks
      if [ -a $CERTSTORE ]; then
          rm $CERTSTORE || exit 1
      fi
 keytool \
  -import \
  -v \
  -trustcacerts \
  -alias 0 \
  -file <(openssl x509 -in ca.pem) \
  -keystore $CERTSTORE \
  -storetype BKS \
  -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
  -providerpath /usr/share/java/bcprov.jar \
  -storepass some-password`

Sollte sofort funktionieren. Ich hatte über einen Tag lang Probleme, selbst nach einer perfekten Antwort von @emmby . Ich hoffe, das hilft jemandem ...

13hsoj
quelle
0

Verwenden Sie diese Klasse

public class WCFs
{
    //  https://192.168.30.8/myservice.svc?wsdl
private static final String NAMESPACE = "http://tempuri.org/";
private static final String URL = "192.168.30.8";
private static final String SERVICE = "/myservice.svc?wsdl";
private static String SOAP_ACTION = "http://tempuri.org/iWCFserviceMe/";


public static Thread myMethod(Runnable rp)
{
    String METHOD_NAME = "myMethod";

    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

    request.addProperty("Message", "Https WCF Running...");
    return _call(rp,METHOD_NAME, request);
}

protected static HandlerThread _call(final RunProcess rp,final String METHOD_NAME, SoapObject soapReq)
{
    final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    int TimeOut = 5*1000;

    envelope.dotNet = true;
    envelope.bodyOut = soapReq;
    envelope.setOutputSoapObject(soapReq);

    final HttpsTransportSE httpTransport_net = new HttpsTransportSE(URL, 443, SERVICE, TimeOut);

    try
    {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() // use this section if crt file is handmake
        {
            @Override
            public boolean verify(String hostname, SSLSession session)
            {
                return true;
            }
        });

        KeyStore k = getFromRaw(R.raw.key, "PKCS12", "password");
        ((HttpsServiceConnectionSE) httpTransport_net.getServiceConnection()).setSSLSocketFactory(getSSLSocketFactory(k, "SSL"));


    }
    catch(Exception e){}

    HandlerThread thread = new HandlerThread("wcfTd"+ Generator.getRandomNumber())
    {
        @Override
        public void run()
        {
            Handler h = new Handler(Looper.getMainLooper());
            Object response = null;

            for(int i=0; i<4; i++)
            {
                response = send(envelope, httpTransport_net , METHOD_NAME, null);

                try
                {if(Thread.currentThread().isInterrupted()) return;}catch(Exception e){}

                if(response != null)
                    break;

                ThreadHelper.threadSleep(250);
            }

            if(response != null)
            {
                if(rp != null)
                {
                    rp.setArguments(response.toString());
                    h.post(rp);
                }
            }
            else
            {
                if(Thread.currentThread().isInterrupted())
                    return;

                if(rp != null)
                {
                    rp.setExceptionState(true);
                    h.post(rp);
                }
            }

            ThreadHelper.stopThread(this);
        }
    };

    thread.start();

    return thread;
}


private static Object send(SoapSerializationEnvelope envelope, HttpTransportSE androidHttpTransport, String METHOD_NAME, List<HeaderProperty> headerList)
{
    try
    {
        if(headerList != null)
            androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope, headerList);
        else
            androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope);

        Object res = envelope.getResponse();

        if(res instanceof SoapPrimitive)
            return (SoapPrimitive) envelope.getResponse();
        else if(res instanceof SoapObject)
            return ((SoapObject) envelope.getResponse());
    }
    catch(Exception e)
    {}

    return null;
}

public static KeyStore getFromRaw(@RawRes int id, String algorithm, String filePassword)
{
    try
    {
        InputStream inputStream = ResourceMaster.openRaw(id);
        KeyStore keystore = KeyStore.getInstance(algorithm);
        keystore.load(inputStream, filePassword.toCharArray());
        inputStream.close();

        return keystore;
    }
    catch(Exception e)
    {}

    return null;
}

public static SSLSocketFactory getSSLSocketFactory(KeyStore trustKey, String SSLAlgorithm)
{
    try
    {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustKey);

        SSLContext context = SSLContext.getInstance(SSLAlgorithm);//"SSL" "TLS"
        context.init(null, tmf.getTrustManagers(), null);

        return context.getSocketFactory();
    }
    catch(Exception e){}

    return null;
}

}}

Ali Bagheri
quelle
0

Geben Sie hier die Bildbeschreibung ein

Ein sspi ist in xamarin android fehlgeschlagen.

Ich habe diese Lösung gefunden; Fügen Sie diesen Code ein, bevor Sie auf einen HTTPS-Link klicken

const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12;
ServicePointManager.SecurityProtocol = Tls12;
vinothswami
quelle
-3

arbeite mit allen https

httpClient = new DefaultHttpClient();

SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
    public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

    public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

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

ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 443, ssf));
Cezarius
quelle
2
Wiederholt nur dieselbe trügerische unsichere Nichtlösung, die bereits in diesem Thread diskutiert und verworfen wurde.
Marquis von Lorne
-3

Es gibt viele Antworten oben, aber ich konnte keine davon richtig zum Laufen bringen (mit meiner begrenzten Zeit). Für alle anderen in der gleichen Situation können Sie den folgenden Code ausprobieren, der für meine Java-Testzwecke perfekt funktioniert hat:

    public static HttpClient wrapClient(HttpClient base) {
    try {
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

            public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        ctx.init(null, new TrustManager[]{tm}, null);
        SSLSocketFactory ssf = new SSLSocketFactory(ctx);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        ClientConnectionManager ccm = base.getConnectionManager();
        SchemeRegistry sr = ccm.getSchemeRegistry();
        sr.register(new Scheme("https", ssf, 443));
        return new DefaultHttpClient(ccm, base.getParams());
    } catch (Exception ex) {
        return null;
    }
}

und rufe an wie:

DefaultHttpClient baseClient = new DefaultHttpClient();
HttpClient httpClient = wrapClient(baseClient );

Referenz: http://tech.chitgoks.com/2011/04/24/how-to-avoid-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-problem-using-apache-httpclient/

Schein
quelle
Zu zitieren EJP: „Genau die gleiche trügerisch unsicher Nicht-Lösung wiederholt , die bereits in diesem Thread diskutiert und entlassen wurde“ .
JWW
-4

Verwenden Sie einfach diese -

public DefaultHttpClient wrapClient(HttpClient base) {
    try {
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

        public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };
    ctx.init(null, new TrustManager[]{tm}, null);
    SSLSocketFactory ssf = new SSLSocketFactory(ctx);
    ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    ClientConnectionManager ccm = base.getConnectionManager();
    SchemeRegistry sr = ccm.getSchemeRegistry();
    sr.register(new Scheme("https", ssf, 443));
    return new DefaultHttpClient(ccm, base.getParams());
} catch (Exception ex) {
    return null;
}
}
Hemant
quelle
Zu zitieren EJP: „Genau die gleiche trügerisch unsicher Nicht-Lösung wiederholt , die bereits in diesem Thread diskutiert und entlassen wurde“ .
JWW
-5

Daniels Antwort war gut, außer dass ich diesen Code ändern musste ...

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

zu diesem Code ...

    ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
    SchemeRegistry registry = ccm.getShemeRegistry()
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    registry.register(new Scheme("https", sf, 443));

um es zum Laufen zu bringen.

Dean Hiller
quelle
5
wie soll das gehen Sie verweisen auf die Registrierung, bevor Sie sie überhaupt erstellt haben!
Matthias B