Confiando em todos os certificados usando HttpClient sobre HTTPS

393

Postou recentemente uma pergunta HttpClientsobre Https over ( encontrado aqui ). Fiz alguns progressos, mas encontrei novos problemas. Como no meu último problema, não consigo encontrar um exemplo em nenhum lugar que funcione para mim. Basicamente, quero que meu cliente aceite qualquer certificado (porque estou apenas apontando para um servidor), mas continuo recebendo umjavax.net.ssl.SSLException: Not trusted server certificate exception.

Então é isso que eu tenho:


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

E aqui está o erro que estou recebendo:

    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
fonte
17
Eu precisava fazer isso para uso interno. Eu realmente espero que você não permita que usuários de fora da sua empresa usem seu aplicativo, pois você o abriu no ataque do meio e eles ficariam vulneráveis ​​a alguém que seqüestrasse sua sessão. no entanto, eu preciso fazer isso temporariamente para alguns testes até obter o certificado real em mãos ... espero que você esteja fazendo isso pelo mesmo tipo temporário de razão ou o aplicativo seja usado apenas internamente.
Dean Hiller
Eu tentei essas soluções no cliente http apache 4.3, mas elas foram descontinuadas. Aqui não está solução obsoleta: stackoverflow.com/a/18941950/2039471 #
Alexander Chzhen 22/13
O Java 1.6 não possui suporte SNI, o que também é problemático nesses cenários - se você não construir a solicitação corretamente, poderá obter um certificado que não corresponda à solicitação. Veja Issues.apache.org/jira/browse/HTTPCLIENT-1119
Bron Davies
2
Esta questão é citada no artigo O Código Mais Perigoso do Mundo como um exemplo de raciocínio falacioso. (artigo de pesquisa: cs.utexas.edu/~shmat/shmat_ccs12.pdf )
mk_

Respostas:

421

Nota: Não implemente isso no código de produção que você utilizará em uma rede em que não confia totalmente. Especialmente qualquer coisa passando pela internet pública.

Sua pergunta é exatamente o que eu quero saber. Depois de fazer algumas pesquisas, a conclusão é a seguinte.

No modo HttpClient, você deve criar uma classe personalizada a partir do org.apache.http.conn.ssl.SSLSocketFactory, não aquele org.apache.http.conn.ssl.SSLSocketFactory. Algumas dicas podem ser encontradas neste post. O tratamento SSL personalizado parou de funcionar no Android 2.2 FroYo .

Um exemplo é como ...

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

e use essa classe ao criar a instância do 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();
    }
}

BTW, o link abaixo é para quem procura a solução HttpURLConnection. Conexão Https Android

Eu testei os dois tipos de soluções acima no froyo, e todos eles funcionam como um encanto nos meus casos. Por fim, o uso de HttpURLConnection pode enfrentar os problemas de redirecionamento, mas isso está além do tópico.

Nota: Antes de decidir confiar em todos os certificados, você provavelmente deve conhecer o site muito bem e não será prejudicial para o usuário final.

De fato, o risco que você assume deve ser considerado com cuidado, incluindo o efeito do site falso de hacker mencionado nos comentários a seguir que apreciei profundamente. Em algumas situações, embora possa ser difícil cuidar de todos os certificados, é melhor conhecer as desvantagens implícitas de confiar em todos eles.

Daniel
fonte
150
esta resposta provavelmente deve observar que confiar em todos os certificados é terrivelmente inseguro e anula todo o propósito do SSL ...
yanokwa
22
@sweeney - Exceto que não é garantido que você esteja conversando com o servidor que pensa estar. Se alguém tiver esfaqueado um servidor DNS, você poderá estar comunicando uma chave de criptografia com o servidor de um hacker.
Richard Szalay 11/11
12
@sweeney Em outras palavras, agora você é passível de ataques man-in-the-middle. Você também deve observar que esse código não atende à especificação: verifique o Javadoc. getAcceptedIssuers()não tem permissão para retornar nulo.
Marquês de Lorne
25
-1 Porque é uma péssima idéia aceitar todos os certificados. É uma pena que existam tantos blogs e tutoriais que guiam alegremente os desenvolvedores Java no caminho de fazer a coisa errada.
Tim Bender
57
+1 Porque eu precisava de uma solução rápida apenas para fins de depuração. Eu não usaria isso na produção devido às preocupações de segurança mencionadas por outros, mas era exatamente isso que eu precisava para testar. Obrigado!
Danation 24/10/12
495

Você basicamente tem quatro soluções em potencial para corrigir uma exceção "Não confiável" no Android usando o httpclient:

  1. Confie em todos os certificados. Não faça isso, a menos que você realmente saiba o que está fazendo.
  2. Crie um SSLSocketFactory personalizado que confie apenas no seu certificado. Isso funciona desde que você saiba exatamente a quais servidores você se conectará, mas assim que precisar se conectar a um novo servidor com um certificado SSL diferente, será necessário atualizar seu aplicativo.
  3. Crie um arquivo de keystore que contenha a "lista principal" de certificados do Android e adicione a sua. Se algum desses documentos expirar no futuro, você será responsável por atualizá-los em seu aplicativo. Não consigo pensar em uma razão para fazer isso.
  4. Crie um SSLSocketFactory personalizado que use o certificado interno KeyStore, mas recorra a um KeyStore alternativo para qualquer coisa que não verifique com o padrão.

Essa resposta usa a solução 4, que me parece a mais robusta.

A solução é usar um SSLSocketFactory que possa aceitar várias KeyStores, permitindo que você forneça seu próprio KeyStore com seus próprios certificados. Isso permite que você carregue certificados de nível superior adicionais, como Thawte, que podem estar ausentes em alguns dispositivos Android. Também permite carregar seus próprios certificados autoassinados. Ele usará primeiro os certificados de dispositivo padrão integrados e utilizará seus certificados adicionais apenas quando necessário.

Primeiro, você deve determinar qual certificado está faltando na sua KeyStore. Execute o seguinte comando:

openssl s_client -connect www.yourserver.com:443

E você verá resultados como os seguintes:

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

Como você pode ver, nosso certificado raiz é da Thawte. Acesse o site do seu provedor e encontre o certificado correspondente. Para nós, estava aqui , e você pode ver que o que precisávamos era o Copyright 2006.

Se você estiver usando um certificado autoassinado, não precisará executar a etapa anterior, pois já possui seu certificado de assinatura.

Em seguida, crie um arquivo de keystore contendo o certificado de assinatura ausente. Crazybob tem detalhes de como fazer isso no Android , mas a idéia é fazer o seguinte:

Se você ainda não o possui, faça o download da biblioteca do fornecedor do castelo insuflável em: http://www.bouncycastle.org/latest_releases.html . Isso seguirá seu caminho de classe abaixo.

Execute um comando para extrair o certificado do servidor e criar um arquivo pem. Nesse caso, mycert.pem.

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

Em seguida, execute os seguintes comandos para criar o keystore.

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

Você notará que o script acima coloca o resultado res/raw/mystore.bks. Agora você tem um arquivo que você carregará no seu aplicativo Android que fornece os certificados ausentes.

Para fazer isso, registre seu SSLSocketFactory para o esquema SSL:

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

Para criar seu 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);
    }
}

E, finalmente, o código AdditionalKeyStoresSSLSocketFactory, que aceita seu novo KeyStore e verifica se o KeyStore interno falha ao validar um certificado SSL:

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

}
empapar
fonte
Hey @emmby, esta parece ser a resposta perfeita para o meu problema, mas ainda não tenho conexão SSL. Você pode dar uma olhada? http://stackoverflow.com/questions/7822381/need-help-understanding-certificate-chains
Matthias B
Obrigado pela excelente redação @emmby! Às vezes, estou recebendo um atraso muito longo e, em seguida, um javax.net.ssl.SSLException: Read error :. Qualquer ideia? Como definir um tempo limite se a solução for a mesma que stackoverflow.com/questions/5909308/android-2-3-4-ssl-problem ?
Edwin Evans
3
@emmby, você poderia dizer onde devo colocar esse código export CLASSPATH = bcprov-jdk16-145.jar CERTSTORE = res / raw / mystore.bks se [-a $ CERTSTORE]; então rm $ CERTSTORE || saída 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
11
Hey @emmby. Estou usando sua solução no meu aplicativo e usando certificado autoassinado do meu servidor, mas obtendo uma CertificateException () no método checkServerTrusted () . Tentei comentar essa exceção de lançamento e funciona. se ele não validar meu certificado de servidor, posso lidar com isso de outra maneira? Você pode orientar qual é a melhor solução nesse caso?
Ankit
7
Isso deve ser marcado como a resposta certa. Uma das respostas mais completas e bem escritas que eu já vi no SO. Dope
Kachi
74

Adicione este código antes do HttpsURLConnectione será feito. Deixa comigo.

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

Espero que isso ajude você.

Alok Gupta
fonte
22
Veja as observações acima na resposta aceita. Essa 'solução' é radicalmente insegura.
Marquês de Lorne
5
Esta é a solução ideal de Q&D. Curto e "simplesmente funciona".
Steve Smith
5
Resposta perfeita para fins de teste !!! E sim, é uma má ideia usar na produção, mas vamos lá ... isso deve ficar claro para todos que olham o título da pergunta. Ele ainda responde melhor / mais curto / com o mesmo nível de segurança (in)!
Levite
34

Esta é uma má ideia. Confiar em qualquer certificado é apenas (muito) um pouco melhor do que não usar SSL. Quando você diz "Quero que meu cliente aceite qualquer certificado (porque só estou apontando para um servidor)", você assume que isso significa que, de alguma forma, apontar para "um servidor" é seguro, o que não ocorre em uma rede pública.

Você está completamente aberto a um ataque intermediário confiando em qualquer certificado. Qualquer pessoa pode fazer proxy da sua conexão estabelecendo uma conexão SSL separada com você e com o servidor final. O MITM tem acesso a toda a sua solicitação e resposta. A menos que você realmente não precise de SSL em primeiro lugar (sua mensagem não tem nada sensível e não faz autenticação), você não deve confiar em todos os certificados às cegas.

Você deve considerar adicionar o certificado público a um jks usando o keytool e usá-lo para criar sua fábrica de soquetes, como esta:

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

Isso tem uma ressalva a ser observada. O certificado expirará eventualmente e o código deixará de funcionar naquele momento. Você pode determinar facilmente quando isso acontecerá olhando para o certificado.

Dan
fonte
5
Se você não estiver usando autenticação de certificado de cliente, do lado do cliente, não precisará de um gerenciador de chaves (use nullno SSLContext.init). You should also use the default algorithms (KMF/TMF.getDefaultAlgorithm() ), instead of hard-coding SunX509` (mais ainda porque o padrão para TMF está realmente PKIXna Sun / Oracle JVM).
Bruno
Existe um arquivo de certificados raiz pronto para usar? (como navegadores fazem)
herrera dani
De onde myjks.jksvem?
Zionpi 24/08/2015
11
@zionpi Gerado usando Java "keytool".
Dan
22

Você pode desativar a verificação de SSL HttpURLConnection para fins de teste desta maneira desde a 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
fonte
2
org.apache.http.conn.ssl.AllowAllHostnameVerifierestá obsoleto.
zackygaurav
2
@zackygaurav De acordo com o javadoc , AllowAllHostnameVerifieré substituído por NoopHostnameVerifier"
DLight 14/03
10

A API do HttpComponents foi alterada. Funciona com o código abaixo.

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
fonte
Usar uma estratégia de confiança personalizada é a resposta certa. Obrigado.
Matt Friedman
10

O código acima em https://stackoverflow.com/a/6378872/1553004 está correto, exceto que DEVE também chamar o verificador de nome de host:

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

Eu me inscrevi no stackoverflow expressamente para adicionar essa correção. Preste atenção ao meu aviso!

Robert Blair
fonte
Depois de verificar o certificado dessa maneira na primeira conexão, o que você faz com as conexões subseqüentes? Você aproveita o conhecimento adquirido com a primeira conexão? E se um certificado falso com o mesmo nome for usado na tentativa de conexão 3?
JWW
6

Estou adicionando uma resposta para aqueles que usam o httpclient-4.5 e provavelmente também funciona para o 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);
    }
}
}
raisercostin
fonte
qual é a nova classe NoopHostnameVerifier ()?
Mushtakim Ahmed Ansari
11
@MushtakimAhmedAnsari From docs: "O NO_OP HostnameVerifier essencialmente desativa a verificação de nome de host. Esta implementação é não operacional e nunca lança a exceção SSLEx."
raisercostin
Obrigado pela ótima resposta.Este deve receber mais votos.
Abhay Dwivedi
Como eu uso isso? ou você está sugerindo que simplesmente ter a classe substituirá as verificações de certificado ssl?
behelit 1/10/19
sim. que httpclient quando usado não vai validar os certificados HTTPS
raisercostin
4

Confiar em todos os certificados não era uma alternativa real para mim, então fiz o seguinte para fazer o HttpsURLConnection confiar em um novo certificado (consulte também http://nelenkov.blogspot.jp/2011/12/using-custom-certificate-trust-store- on.html ).

  1. Obter o certificado; Fiz isso exportando o certificado no Firefox (clique no pequeno ícone de cadeado, obtenha detalhes do certificado, clique em exportar) e usei o portecle para exportar um armazenamento confiável (BKS).

  2. Carregue o armazenamento confiável em /res/raw/geotrust_cert.bks com o seguinte código:

        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
fonte
Eu recebo esse erro. IOExceptionjavax.net.ssl.SSLPeerUnverifiedException: No peer certificate. Isso ao executar a chamada de execução real no HttpClient após a conclusão da configuração acima.
Michael
3

Aqui está uma versão muito simples usando o código httpclient 4.1.2. Isso pode ser modificado para qualquer algoritmo de confiança que você achar melhor.

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
fonte
3

Estou procurando resposta de "emmby" (respondeu 16 de junho de 2011 às 21:29), item 4: "Crie um SSLSocketFactory personalizado que use o certificado interno KeyStore, mas recorra a um KeyStore alternativo por qualquer falha para verificar com o padrão ".

Esta é uma implementação simplificada. Carregue o keystore do sistema e mescle com o keystore do aplicativo.

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

Um modo simples de converter de JKS para 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

* Nota: No Android 4.0 (ICS), o Trust Store mudou, mais informações: http://nelenkov.blogspot.com.es/2011/12/ics-trust-store-implementation.html

ggrandes
fonte
3

Para aqueles que desejam permitir que todos os certificados funcionem (para fins de teste) no OAuth, siga estas etapas:

1) Faça o download do código-fonte da API do Android OAuth aqui: https://github.com/kaeppler/signpost

2) Encontre o arquivo "CommonsHttpOAuthProvider" classe

3) Altere como abaixo:

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

O "MySSLSocketFactory" acima é baseado na resposta aceita. Para facilitar ainda mais, aqui está a aula completa:

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

}

Espero que isso ajude alguém.

Tiago
fonte
11
A questão era HttpCliente HTTPS; não OAuth para Android de um projeto do GitHub.
jww
3

Eu usei isso e funciona para mim em todos os sistemas operacionais.

/**
 * 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
fonte
Olá @ yegor256, eu estou usando esse código, mas ainda recebendo problema SSL handshake
user2028
0

Qualquer pessoa que ainda esteja com problemas com os Certificados SSL da StartCom no Android 2.1, visite https://www.startssl.com/certs/ e faça o download do ca.pem, agora na resposta fornecida por @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`

com

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

Deve funcionar fora da caixa. Eu estava lutando por mais de um dia, mesmo depois de uma resposta perfeita do @emmby .. Espero que isso ajude alguém ...

13hsoj
fonte
0

use esta classe

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
fonte
0

insira a descrição da imagem aqui

Um sspi falhou no xamarin android.

Eu encontrei esta solução; coloque esse código antes de acessar um link HTTPS

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

trabalhar com todos os 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
fonte
2
Apenas repete a mesma não-solução falaciosa e insegura que já foi discutida e descartada nesta discussão.
Marquês de Lorne
-3

Há muitas respostas acima, mas não consegui fazer com que nenhuma delas funcionasse corretamente (com meu tempo limitado); portanto, para qualquer outra pessoa na mesma situação, você pode tentar o código abaixo, que funcionou perfeitamente para meus propósitos de teste de java:

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

e chame como:

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

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

farsa, falso
fonte
Para citar o EJP: "Apenas repete a mesma não-solução falaciosa e insegura que já foi discutida e descartada neste tópico" .
JWW
-4

Basta usar isso -

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
fonte
Para citar o EJP: "Apenas repete a mesma não-solução falaciosa e insegura que já foi discutida e descartada neste tópico" .
JWW
-5

A resposta de Daniel foi boa, exceto que eu tive que mudar esse código ...

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

para este código ...

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

para fazê-lo funcionar.

Dean Hiller
fonte
5
como isso deve funcionar? você faz referência ao registro antes mesmo de criá-lo!
Matthias B