HTTPS üzerinden HttpClient kullanarak tüm sertifikalara güvenme


393

Son zamanlarda HttpClientHttps ( burada bulundu ) ile ilgili bir soru yayınladı . Biraz ilerledim, ama yeni sorunlarla karşılaştım. Son sorunumda olduğu gibi, benim için işe yarayan hiçbir yerde bir örnek bulamıyorum. Temel olarak, müvekkilimin herhangi bir sertifikayı kabul etmesini istiyorum (çünkü sadece bir sunucuya işaret ediyorum)javax.net.ssl.SSLException: Not trusted server certificate exception.

Yani sahip olduğum şey bu:


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

İşte aldığım hata:

    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

17
Bunu dahili kullanım için yapmam gerekiyordu. Umarım şirket dışında kullanıcıların uygulamanızı kullanmasına izin vermiyorsunuz, çünkü orta saldırıda adama açtınız ve daha sonra oturumlarını ele geçiren birisine karşı savunmasız kalacaklardı. yine de, ben gerçek sertifika elde ..... kadar bazı geçici test için bu geçici yapmak gerekir umarım aynı geçici tür nedeni için yapıyoruz veya uygulama sadece dahili olarak kullanılır.
Dean Hiller

4.3 apache http istemcisinde bu çözümleri denedim, ancak çoğunlukla kullanımdan kaldırıldı. Kullanımdan kaldırılmış bir çözüm değil: stackoverflow.com/a/18941950/2039471
Alexander Chzhen

Java 1.6, bu senaryolarda da sorunlu olan SNI desteğine sahip değildir - isteği düzgün bir şekilde oluşturmazsanız, istekle eşleşmeyen bir sertifika alabilirsiniz. Bkz issues.apache.org/jira/browse/HTTPCLIENT-1119
Bron Davies

2
Bu soru, yanlış akıl yürütmenin bir örneği olarak Dünya'nın En Tehlikeli Kanunu'nda yer almaktadır. (araştırma makalesi: cs.utexas.edu/~shmat/shmat_ccs12.pdf )
mk_

Yanıtlar:


421

Not: Bunu, tamamen güvenmediğiniz bir ağda kullanacağınız üretim koduna uygulamayın. Özellikle halka açık internet üzerinden her şey.

Sorunuz sadece bilmek istediğim şey. Biraz araştırma yaptıktan sonra sonuç şu şekildedir.

HttpClient yönteminde, org.apache.http.conn.ssl.SSLSocketFactory öğesinden değil, org.apache.http.conn.ssl.SSLSocketFactory öğesinden özel bir sınıf oluşturmanız gerekir. Bu yazıda bazı ipuçları bulunabilir Özel SSL kullanımı Android 2.2 FroYo'da çalışmayı durdurdu .

Bir örnek ...

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

ve HttpClient örneği oluştururken bu sınıfı kullanın.

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

BTW, aşağıdaki bağlantı HttpURLConnection çözümü arayan biri içindir. Https Bağlantısı Android

Froyo üzerinde yukarıdaki iki çeşit çözümü test ettim ve hepsi benim durumumda bir cazibe gibi çalışıyor. Son olarak, HttpURLConnection kullanmak yönlendirme sorunlarıyla karşılaşabilir, ancak bu konunun ötesindedir.

Not: Tüm sertifikalara güvenmeye karar vermeden önce, büyük olasılıkla siteyi tam olarak bilmeniz gerekir ve son kullanıcıya zarar vermeyecektir.

Gerçekten de, hacker'ın aşağıdaki yorumlarda derinden takdir ettiğim sahte sitenin etkisi de dahil olmak üzere, aldığınız risk dikkatle düşünülmelidir. Bazı durumlarda, tüm sertifikalarla ilgilenmek zor olsa da, hepsine güvenmek için örtük dezavantajları daha iyi bilirsiniz.


150
Bu cevap muhtemelen tüm sertifikalara güvenmek korkunç güvensiz olduğunu ve tüm ssl amacını geçersiz
kılar

22
@sweeney - Olduğunu düşündüğünüz sunucuyla konuştuğunuzun garanti edilmemesi dışında. Birisi bir DNS sunucusunu ele geçirmişse, bir şifreleme anahtarını bilgisayar korsanının sunucusuyla iletiyor olabilirsiniz.
Richard Szalay

12
Diğer bir deyişle, artık ortadaki adam saldırılarından sorumlu olacaksınız. Ayrıca, kodun spesifikasyonu karşılamadığını da not etmelisiniz: Javadoc'u kontrol edin. getAcceptedIssuers()boş döndürülmesine izin verilmiyor.
Lorne Marquis

25
-1 Çünkü tüm sertifikaları kabul etmek korkunç bir fikir. Java geliştiricilerine yanlış bir şey yapma yolu boyunca mutlu bir şekilde rehberlik eden çok sayıda blog ve öğretici olması çok kötü.
Tim Bender

57
+1 Çünkü sadece hata ayıklama amacıyla hızlı bir çözüme ihtiyacım vardı. Başkalarının bahsettiği güvenlik endişeleri nedeniyle bunu üretimde kullanmam, ancak test için tam olarak ihtiyacım olan buydu. Teşekkür ederim!
Dans

495

Temelde, httpclient kullanarak Android'de "Güvenilir Değil" özel durumunu düzeltmek için dört potansiyel çözümünüz vardır:

  1. Tüm sertifikalara güvenin. Ne yaptığınızı gerçekten bilmiyorsanız bunu yapmayın.
  2. Yalnızca sertifikanıza güvenen özel bir SSLSocketFactory oluşturun. Bu, tam olarak hangi sunuculara bağlanacağınızı bildiğiniz sürece çalışır, ancak farklı bir SSL sertifikası olan yeni bir sunucuya bağlanmanız gerektiğinde uygulamanızı güncellemeniz gerekir.
  3. Android'in sertifikaların "ana listesini" içeren bir anahtar deposu dosyası oluşturun ve sonra kendinizinkini ekleyin. Bu sertifikalardan herhangi birinin süresi dolarsa, uygulamanızda güncellemekten siz sorumlusunuz. Bunu yapmak için bir neden düşünemiyorum.
  4. Yerleşik KeyStore sertifikasını kullanan, ancak varsayılan ile doğrulanamayan her şey için alternatif bir KeyStore'a dayanan özel bir SSLSocketFactory oluşturun.

Bu cevap benim için en sağlam gibi görünen # 4 çözümünü kullanıyor.

Çözüm, birden fazla KeyStore kabul edebilen bir SSLSocketFactory kullanmak ve kendi KeyStore'unuzu kendi sertifikalarınızla tedarik etmenizi sağlamaktır. Bu, bazı Android cihazlarda eksik olabilecek Thawte gibi ek üst düzey sertifikalar yüklemenizi sağlar. Ayrıca kendi imzasını taşıyan sertifikalarınızı da yüklemenizi sağlar. Öncelikle yerleşik varsayılan aygıt sertifikalarını kullanır ve yalnızca gerektiğinde ek sertifikalarınıza geri döner.

İlk olarak, KeyStore'unuzda hangi sertifikanın eksik olduğunu belirlemek isteyeceksiniz. Aşağıdaki komutu çalıştırın:

openssl s_client -connect www.yourserver.com:443

Ve çıktıyı aşağıdaki gibi göreceksiniz:

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

Gördüğünüz gibi, kök sertifikamız Thawte'den. Sağlayıcınızın web sitesine gidin ve ilgili sertifikayı bulun. Bizim için buradaydı ve ihtiyacımız olanın Telif Hakkı 2006 olduğunu görebilirsiniz.

Kendinden imzalı bir sertifika kullanıyorsanız, imzalama sertifikanıza zaten sahip olduğunuzdan önceki adımı uygulamanıza gerek yoktu.

Ardından, eksik imzalama sertifikasını içeren bir anahtar deposu dosyası oluşturun. Crazybob, bunu Android'de nasıl yapacağınızla ilgili ayrıntılara sahiptir , ancak fikir aşağıdakileri yapmaktır:

Henüz sahip değilseniz, bouncy castle sağlayıcı kütüphanesini şu adresten indirin : http://www.bouncycastle.org/latest_releases.html . Bu, aşağıdaki sınıf yolunuzda devam edecek.

Sertifikayı sunucudan ayıklamak ve bir pem dosyası oluşturmak için bir komut çalıştırın. Bu durumda, mycert.pem.

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

Ardından anahtar deposunu oluşturmak için aşağıdaki komutları çalıştırın.

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

Yukarıdaki komut dosyasının sonucu yerleştirdiğini göreceksiniz res/raw/mystore.bks. Artık Android uygulamanıza yükleyeceğiniz ve eksik sertifikaları sağlayan bir dosyanız var.

Bunu yapmak için SSL şeması için SSLSocketFactory'nizi kaydedin:

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

SSLSocketFactory'nizi oluşturmak için:

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

Son olarak, yeni KeyStore'unuzu kabul eden ve yerleşik KeyStore'un bir SSL sertifikasını doğrulayamadığını kontrol eden AdditionalKeyStoresSSLSocketFactory kodu:

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

}

Hey @ emmby, bu sorunum için mükemmel bir yanıt gibi görünüyor, ancak hala SSL bağlantısı almıyorum. Lütfen bir göz atabilir misiniz? http://stackoverflow.com/questions/7822381/need-help-understanding-certificate-chains
Matthias B

@Emmby adlı harika yazı için teşekkürler! Bazen gerçekten uzun bir gecikme ve sonra bir javax.net.ssl.SSLException: Okuma hatası: alıyorum. Herhangi bir fikir? Çözüm stackoverflow.com/questions/5909308/android-2-3-4-ssl-problem ile aynı ise zaman aşımı nasıl ayarlayabilirim ?
Edwin Evans

3
@emmby, bu kodu nereye koymam gerektiğini söyleyebilir misiniz CLASSPATH = bcprov-jdk16-145.jar CERTSTORE = res / raw / mystore.bks eğer [-a $ CERTSTORE]; sonra rm $ CERTSTORE || çıkış 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 bazı şifre
Rikki Tikki Tavi

1
Hey @emmby. Benim uygulamasında çözümü kullanarak ve benim sunucunun kendine imzalanan sertifika kullanarak ancak alıyorum CertificateException () içinde checkServerTrusted () yöntemi. Bu istisna atmaya yorum yapmayı denedim ve işe yarıyor. benim sunucu sertifika doğrulamıyorsa o zaman başka bir şekilde ele alabilir miyim, bu durumda en iyi çözüm nedir lütfen rehberlik edebilir misiniz?
Ankit

7
Bu doğru cevap olarak işaretlenmelidir. Şimdiye kadar gördüğüm en kapsamlı ve iyi yazılmış cevaplardan biri. Dope
Kachi

74

Bu kodu önce ekleyin HttpsURLConnectionve yapılacaktır. Anladım.

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

Umarım bu sana yardımcı olur.


22
Kabul edilen cevabın altındaki yukarıdaki açıklamalara bakınız. Bu 'çözüm' radikal olarak güvensizdir.
Lorne Marquis

5
Bu ideal soru-cevap çözümüdür. Kısa ve "sadece çalışır".
Steve Smith

5
Test amaçlı mükemmel cevap !!! Ve evet, üretimde kullanmak kötü bir fikir, ama hadi ... soru başlığına bakan herkes için açık olmalı. Yine de en iyi / en kısa / aynı güvenlik seviyesi ile cevap veriyor!
Levite

34

Bu kötü bir fikir. Herhangi bir sertifikaya güvenmek, hiçbir SSL kullanmamaktan çok (biraz) daha iyidir. "İstemcimin herhangi bir sertifikayı kabul etmesini istiyorum (yalnızca bir sunucuya işaret ettiğim için)" dediğinizde, bunun, bir şekilde "bir sunucuya" işaret etmenin güvenli olduğu anlamına gelir ki bu, genel bir ağda değildir.

Herhangi bir sertifikaya güvenerek ortadaki adam saldırısına tamamen açıksınız. Herkes sizinle ve son sunucu ile ayrı bir SSL bağlantısı kurarak bağlantınızı proxy yapabilir. MITM daha sonra tüm talebinize ve yanıtınıza erişebilir. İlk etapta SSL'ye gerçekten ihtiyacınız olmadıkça (mesajınızda hassas hiçbir şey yoktur ve kimlik doğrulama yapılmazsa) tüm sertifikalara körü körüne güvenmemelisiniz.

Keytool kullanarak bir jks genel cert eklemek ve bu gibi soket fabrika kurmak için bunu kullanmayı düşünmelisiniz:

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

Dikkat edilmesi gereken bir uyarı var. Sertifikanın sonunda süresi dolar ve kodun o anda çalışması durur. Sertifikaya bakarak bunun ne zaman olacağını kolayca belirleyebilirsiniz.


5
Eğer istemci sertifikası kimlik doğrulamasını kullanmıyorsanız, istemci tarafında, bir KeyManager (kullanımını gerekmez nulliçinde SSLContext.init). You should also use the default algorithms (KMF/TMF.getDefaultAlgorithm() ), instead of hard-coding SunX509` (daha çok TMF için varsayılan aslında çünkü PKIX. Güneş / Oracle JVM üzerine)
Bruno

Kullanıma hazır bir kök sertifika dosyası var mı? (tarayıcılar gibi)
dani herrera

Nereden myjks.jksgeldi?
zionpi

1
@zionpi Java "keytool" kullanılarak oluşturulur.
Dan

22

API 8'den beri HttpURLConnection SSL kontrolünü test amacıyla bu şekilde devre dışı bırakabilirsiniz:

    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    if (conn instanceof HttpsURLConnection) {
        HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
        httpsConn.setSSLSocketFactory(SSLCertificateSocketFactory.getInsecure(0, null));
        httpsConn.setHostnameVerifier(new AllowAllHostnameVerifier());
    }

2
org.apache.http.conn.ssl.AllowAllHostnameVerifierkullanımdan kaldırıldı.
zackygaurav

2
@zackygaurav göre javadoc , AllowAllHostnameVerifieryerine NoopHostnameVerifier"
Platinum

10

HttpComponents API'si değişti. Aşağıdaki kodla çalışır.

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

Özel bir güven stratejisi kullanmak doğru cevaptır. Teşekkürler.
Matt Friedman

10

Https://stackoverflow.com/a/6378872/1553004 içindeki yukarıdaki kod doğrudur, ancak ana bilgisayar adı doğrulayıcısını da çağırması GEREKİR:

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

Bu düzeltmeyi eklemek için açıkça stackoverflow'a kaydoldum. Uyarımı dikkate al!


İlk bağlantıda sertifikayı bu şekilde doğruladıktan sonra, sonraki bağlantılarda ne yaparsınız? İlk bağlantıdan edindiğiniz bilgilerden faydalanıyor musunuz? Bağlantı denemesi 3'te aynı ada sahip sahte bir sertifika kullanılırsa ne olur?
jww

6

Ben httpclient-4.5 kullananlara bir yanıt ekliyorum ve muhtemelen 4.4 için de çalışıyor.

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

yeni NoopHostnameVerifier () sınıfı nedir?
Mushtakim Ahmed Ansari

1
@MushtakimAhmedAnsari Dokümanlar'dan: "NO_OP HostnameVerifier aslında ana bilgisayar adı doğrulamasını kapatır. Bu uygulama bir işlem yapılmaz ve SSLException'ı hiçbir zaman atmaz."
raisercostin

Harika cevap için teşekkürler. Bu daha fazla oy almak gerekir.
Abhay Dwivedi

Bunu nasıl kullanabilirim? ya da sadece sınıfa sahip olmanın ssl sertifika doğrulamalarını geçersiz kılacağını mı düşünüyorsunuz?
behelit

Evet. kullanıldığında httpClient'in https sertifikalarını doğrulamayacağını unutmayın
raisercostin

4

Tüm sertifikalara güvenmek benim için gerçek bir alternatif değildi, bu yüzden HttpsURLConnection'ın yeni bir sertifikaya güvenmesini sağlamak için aşağıdakileri yaptım (ayrıca bkz. Http://nelenkov.blogspot.jp/2011/12/using-custom-certificate-trust-store- on.html ).

  1. Sertifikayı alın; Bunu Firefox'ta sertifikayı dışa aktararak yaptım (küçük kilit simgesini tıklayın, sertifika ayrıntılarını alın, dışa aktar'ı tıklayın), ardından bir truststore'u (BKS) dışa aktarmak için portecle'ı kullandım .

  2. Truststore'u /res/raw/geotrust_cert.bks sitesinden aşağıdaki kodla yükleyin:

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

Bu hatayı alıyorum. IOExceptionjavax.net.ssl.SSLPeerUnverifiedException: No peer certificate. Yukarıdaki kurulum tamamlandıktan sonra HttpClient üzerinde gerçek yürütme çağrısı yaparken bu.
Michael

3

4.1.2 httpclient kodunu kullanarak çok basit bir sürümü. Bu daha sonra uygun gördüğünüz herhangi bir güven algoritmasına değiştirilebilir.

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

3

"Emmby" (21 Haziran 29, 21: 29'da cevaplandı) yanıtından baktım, madde 4: "KeyStore yerleşik sertifikasını kullanan, ancak başarısız bir şey için alternatif bir KeyStore'a geri dönen özel bir SSLSocketFactory oluşturun varsayılan ile doğrulamak için. "

Bu basitleştirilmiş bir uygulamadır. Sistem anahtar deposunu yükleyin ve uygulama anahtar deposuyla birleştirin.

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

JKS'den BKS'ye dönüştürmek için basit bir mod:

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

* Not: Android 4.0'da (ICS) Güven Mağazası değişti, daha fazla bilgi: http://nelenkov.blogspot.com.es/2011/12/ics-trust-store-implementation.html


3

Tüm sertifikaların OAuth üzerinden çalışmasına (test amacıyla) izin vermek isteyenler için şu adımları izleyin:

1) Android OAuth API'sının kaynak kodunu buradan indirin: https://github.com/kaeppler/signpost

2) "CommonsHttpOAuthProvider" sınıfını bulun

3) aşağıdaki gibi değiştirin:

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

Yukarıdaki "MySSLSocketFactory" kabul edilen cevaba dayanmaktadır. Daha da kolaylaştırmak için tüm sınıf burada:

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

}

Umarım bu birine yardımcı olur.


1
Soru şuydu HttpClientve HTTPS; GitHub projesinden Android için OAuth değil.
jww

3

Bunu kullandım ve tüm işletim sistemlerinde benim için çalışıyor.

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

Merhaba @ yegor256, bu kodu kullanıyorum, ancak yine de SSL el sıkışma sorunu alıyorum
user2028


0

Herhangi vücut hala Android 2.1 ziyaret StartCom SSL Sertifikaları ile mücadele https://www.startssl.com/certs/ ve şimdi, ca.pem indirmek cevap tarafından sağlanan @emmby yerine

`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`

ile

 `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`

Kutunun dışında çalışmalıdır. @Emmby'nin mükemmel cevabından sonra bile bir günden fazla uğraşıyordum .. Umarım bu birine yardımcı olur ...


0

bu sınıfı kullan

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

}


0

resim açıklamasını buraya girin

Bir sspi xamarin androidinde başarısız oldu.

Bu çözümü buldum; bir HTTPS bağlantısına çarpmadan önce bu kodu girin

const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12;
ServicePointManager.SecurityProtocol = Tls12;

-3

tüm https ile çalış

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

2
Sadece bu konuda tartışılmış ve reddedilmiş olan aynı yanlış güvensiz çözümü tekrarlıyor.
Lorne Marquis

-3

Yukarıda birçok cevap var ama ben (sınırlı bir süre ile) doğru çalışmalarını alamadım, bu yüzden aynı durumda başka biri için benim java test amacıyla mükemmel çalıştı aşağıdaki kodu deneyebilirsiniz:

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

ve şöyle arayın:

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

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


EJP'den alıntı yapmak için: "Bu konuda zaten tartışılmış ve reddedilmiş olan aynı yanlış güvensiz çözümü çözüyor . "
jww

-4

Bunu kullanın -

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

EJP'den alıntı yapmak için: "Bu konuda zaten tartışılmış ve reddedilmiş olan aynı yanlış güvensiz çözümü çözüyor . "
jww

-5

Daniel'in cevabı iyiydi, ancak bu kodu değiştirmek zorunda kaldım ...

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

bu koda ...

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

işe almak için.


5
bu nasıl olmalı? hatta yaratmadan önce kayıt referans!
Matthias B
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.