android - without - java.security.cert.certpathvalidatorexception: trust anchor for certification path not found.



aceitando conexões HTTPS com certificados autoassinados (8)

Estou tentando fazer conexões HTTPS, usando HttpClient lib, mas o problema é que, desde que o certificado não é assinado por uma autoridade de certificação (CA) reconhecida como Verisign , GlobalSIgn , etc., listada no conjunto de certificados confiáveis ​​do Android , Eu continuo recebendo javax.net.ssl.SSLException: Not trusted server certificate .

Vi soluções em que você simplesmente aceita todos os certificados, mas e se eu quiser perguntar ao usuário?

Eu quero obter um diálogo semelhante ao do navegador, permitindo que o usuário decida continuar ou não. De preferência eu gostaria de usar o mesmo certificatestore como o navegador. Alguma ideia?

https://code.i-harness.com


A primeira coisa que você precisa fazer é definir o nível de verificação. Tais níveis não são muito:

  • ALLOW_ALL_HOSTNAME_VERIFIER
  • BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
  • STRICT_HOSTNAME_VERIFIER

Embora o método setHostnameVerifier () seja obsoleto para o novo apache da biblioteca, mas para a versão no Android SDK é normal. E assim tomamos ALLOW_ALL_HOSTNAME_VERIFIER e configuramos na fábrica de métodos SSLSocketFactory.setHostnameVerifier() .

Em seguida, você precisa definir nossa fábrica para o protocolo para https. Para fazer isso, basta chamar o método SchemeRegistry.register() .

Então você precisa criar um DefaultHttpClient com SingleClientConnManager . Também no código abaixo você pode ver que no padrão também usaremos nosso sinalizador ( ALLOW_ALL_HOSTNAME_VERIFIER ) pelo método HttpsURLConnection.setDefaultHostnameVerifier()

Abaixo do código funciona para mim:

HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

DefaultHttpClient client = new DefaultHttpClient();

SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());

// Set verifier     
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

// Example send http request
final String url = "https://encrypted.google.com/";
HttpPost httpPost = new HttpPost(url);
HttpResponse response = httpClient.execute(httpPost);

A resposta principal não funcionou para mim. Após algumas investigações, encontrei as informações necessárias sobre "Desenvolvedor Android": https://developer.android.com/training/articles/security-ssl.html#SelfSigned

Criando uma implementação vazia do X509TrustManager fez o truque:

private static class MyTrustManager implements 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;
    }

}

...

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
try
{
    // Create an SSLContext that uses our TrustManager
    SSLContext context = SSLContext.getInstance("TLS");
    TrustManager[] tmlist = {new MyTrustManager()};
    context.init(null, tmlist, null);
    conn.setSSLSocketFactory(context.getSocketFactory());
}
catch (NoSuchAlgorithmException e)
{
    throw new IOException(e);
} catch (KeyManagementException e)
{
    throw new IOException(e);
}
conn.setRequestMethod("GET");
int rcode = conn.getResponseCode();

Por favor, esteja ciente de que esta implementação vazia do TustManager é apenas um exemplo e usá-lo em um ambiente produtivo causaria uma grave ameaça à segurança!


Este é um problema resultante da falta de suporte a SNI (Server Name Identification) inA, ndroid 2.x. Eu estava lutando com este problema por uma semana até me deparar com a seguinte pergunta, que não só dá uma boa base para o problema, mas também fornece uma solução eficaz e funcional, desprovida de quaisquer falhas de segurança.

Erro 'No peer certificate' no Android 2.3, mas NÃO em 4


Eu escrevi pequena biblioteca ssl-utils-android para confiar certificado particular no Android.

Você pode simplesmente carregar qualquer certificado, dando o nome do arquivo do diretório de ativos.

Uso:

OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());

Nenhuma dessas correções funcionou para minha plataforma de desenvolvimento SDK 16, Release 4.1.2, então encontrei uma solução alternativa.

Meu aplicativo armazena dados no servidor usando " http://www.example.com/page.php?data=somedata "

Recentemente o page.php foi movido para " https://www.secure-example.com/page.php " e eu continuo recebendo "javax.net.ssl.SSLException: Not trusted server certificate".

Em vez de aceitar todos os certificados para apenas uma única página, comecei com este guia e resolvi meu problema ao escrever minha própria página.php publicada em " http://www.example.com/page.php "

<?php

caronte ("https://www.secure-example.com/page.php");

function caronte($url) {
    // build curl request
    $ch = curl_init();
    foreach ($_POST as $a => $b) {
        $post[htmlentities($a)]=htmlentities($b);
    }
    curl_setopt($ch, CURLOPT_URL,$url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($post));

    // receive server response ...
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $server_output = curl_exec ($ch);
    curl_close ($ch);

    echo $server_output;
}

?>

O Google recomenda o uso do Android Volley para conexões HTTP / HTTPS , já que esse HttpClient está obsoleto. Então, você sabe a escolha certa :).

E também, NEVER NUKE Certificados SSL (NUNCA !!!).

Para nuke Certificados SSL, é totalmente contra a finalidade do SSL, que está promovendo a segurança . Não há nenhuma sensação de usar SSL, se você está planejando para bombardear todos os certificados SSL que vem. Uma solução melhor seria, não usar SSL, ou uma solução melhor, seria criar um TrustManager personalizado em seu App + usando o Android Volley para conexões HTTP / HTTPS.

Aqui está um Gist que eu criei, com um LoginApp básico, realizando conexões HTTPS, usando um certificado auto-assinado no lado do servidor, aceito no aplicativo.

Aqui está também outra Gist que pode ajudar, para criar Certificados SSL Auto-assinados para configurar em seu servidor e também usando o certificado em seu aplicativo. Muito importante: você deve copiar o arquivo .crt que foi gerado pelo script acima, para o diretório "raw" do seu projeto Android.


Talvez isso seja útil ... funciona em clientes java usando certificados auto-assinados (não há verificação do certificado). Tenha cuidado e use-o apenas para casos de desenvolvimento, porque isso não é seguro de todo !!

Como ignorar erros de certificado SSL no Apache HttpClient 4.0

Espero que funcione no Android apenas adicionando biblioteca HttpClient ... boa sorte !!


Veja como você pode adicionar certificados adicionais ao seu KeyStore para evitar esse problema: Confiando em todos os certificados usando o HttpClient por HTTPS

Ele não perguntará ao usuário como você pergunta, mas diminuirá a probabilidade de o usuário apresentar um erro "Certificado de servidor não confiável".





ca