Postou recentemente uma pergunta HttpClient
sobre 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
java
ssl
https
certificate
apache-httpclient-4.x
harrisonlee
fonte
fonte
Respostas:
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 ...
e use essa classe ao criar a instância do HttpClient.
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.
fonte
getAcceptedIssuers()
não tem permissão para retornar nulo.Você basicamente tem quatro soluções em potencial para corrigir uma exceção "Não confiável" no Android usando o httpclient:
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:
E você verá resultados como os seguintes:
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.
Em seguida, execute os seguintes comandos para criar o keystore.
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:
Para criar seu SSLSocketFactory:
E, finalmente, o código AdditionalKeyStoresSSLSocketFactory, que aceita seu novo KeyStore e verifica se o KeyStore interno falha ao validar um certificado SSL:
fonte
http://stackoverflow.com/questions/7822381/need-help-understanding-certificate-chains
Adicione este código antes do
HttpsURLConnection
e será feito. Deixa comigo.Espero que isso ajude você.
fonte
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:
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.
fonte
null
noSSLContext.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á realmentePKIX
na Sun / Oracle JVM).myjks.jks
vem?Você pode desativar a verificação de SSL HttpURLConnection para fins de teste desta maneira desde a API 8:
fonte
org.apache.http.conn.ssl.AllowAllHostnameVerifier
está obsoleto.AllowAllHostnameVerifier
é substituído porNoopHostnameVerifier
"A API do HttpComponents foi alterada. Funciona com o código abaixo.
fonte
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:
Eu me inscrevi no stackoverflow expressamente para adicionar essa correção. Preste atenção ao meu aviso!
fonte
Estou adicionando uma resposta para aqueles que usam o httpclient-4.5 e provavelmente também funciona para o 4.4.
fonte
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 ).
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).
Carregue o armazenamento confiável em /res/raw/geotrust_cert.bks com o seguinte código:
fonte
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.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.
fonte
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.
Um modo simples de converter de JKS para BKS:
* 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
fonte
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:
O "MySSLSocketFactory" acima é baseado na resposta aceita. Para facilitar ainda mais, aqui está a aula completa:
}
Espero que isso ajude alguém.
fonte
HttpClient
e HTTPS; não OAuth para Android de um projeto do GitHub.Eu usei isso e funciona para mim em todos os sistemas operacionais.
fonte
Basta adicionar
-Dtrust_all_cert=true
argumentos à VM. Este argumento diz ao java para ignorar as verificações de certificado.fonte
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
com
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 ...
fonte
use esta classe
}
fonte
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
fonte
trabalhar com todos os https
fonte
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:
e chame como:
Referência: http://tech.chitgoks.com/2011/04/24/how-to-avoid-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-problem-using-apache-httpclient/
fonte
Basta usar isso -
fonte
A resposta de Daniel foi boa, exceto que eu tive que mudar esse código ...
para este código ...
para fazê-lo funcionar.
fonte