Note-se que as respostas a esta pergunta não fazem mais do que o solicitado: elas permitem que você ignore o erro, mas não soluciona o problema subjacente (um pouco como remover as baterias de um alarme de fumaça em vez de apagar o fogo ) Os certificados têm o objetivo de garantir a segurança da conexão SSL / TLS. Ignorar esses erros introduz uma vulnerabilidade ao ataque do MITM. Use certificados de teste em vez de ignorar o erro.
"como remover as baterias de um alarme de fumaça" Você pode dar a outros desenvolvedores o benefício da dúvida e supor que eles sabem o que estão fazendo. Talvez a motivação para esta pergunta seja o teste local e o OP deseje executar um teste rápido sem passar pelas quantidades horríveis de clichê Java necessárias para configurar até mesmo um ambiente SSL simples. Talvez alguém possa responder a pergunta sem entrar em uma palestra "mais santa do que você".
Mike
Ou seja, em nosso servidor JIRA interno da empresa, existem alguns "certificados baseados em políticas de segurança do Windows", válidos em máquinas Windows incluídas no domínio e não válidas em outras. Não consigo controlar esta política e ainda quero chamar a API REST do JIRA.
Odiszapc
1
@Bruno A incapacidade de desativar os detectores de fumaça por um período de 30 a 60 minutos, ao lidar com um pequeno incêndio na cozinha, mostra uma insana falta de percepção dos padrões de uso por algum funcionário legal em algum momento em que sinto fronteiras do crime. O fato de existir um conceito de "remover baterias de um alarme de fumaça" prova isso. Sinto o mesmo nível de raiva por ter que obter certificados para trabalhar em um teste simples que sei que não tem implicações de segurança. A existência desta questão prova isso.
Bill K
Respostas:
84
Você precisa criar um SSLContext com seu próprio TrustManager e criar um esquema HTTPS usando esse contexto. Aqui está o código,
SSLContext sslContext =SSLContext.getInstance("SSL");// set up a TrustManager that trusts everything
sslContext.init(null,newTrustManager[]{new X509TrustManager(){public X509Certificate[] getAcceptedIssuers(){System.out.println("getAcceptedIssuers =============");returnnull;}publicvoid checkClientTrusted(X509Certificate[] certs,String authType){System.out.println("checkClientTrusted =============");}publicvoid checkServerTrusted(X509Certificate[] certs,String authType){System.out.println("checkServerTrusted =============");}}},newSecureRandom());SSLSocketFactory sf =newSSLSocketFactory(sslContext);Scheme httpsScheme =newScheme("https",443, sf);SchemeRegistry schemeRegistry =newSchemeRegistry();
schemeRegistry.register(httpsScheme);// apache HttpClient version >4.2 should use BasicClientConnectionManagerClientConnectionManager cm =newSingleClientConnManager(schemeRegistry);HttpClient httpClient =newDefaultHttpClient(cm);
Digamos que eu não queira comprar um certificado SSL válido para o meu site e só queira usá-lo, esse código pode ajudar? Por que não vejo nenhuma parte em que um URL é necessário ou o tratamento de exceções é necessário?
Viet
19
Hmm, está me dizendo que 'new SSLSocketFactory (ssslCont)' está esperando um KeyStore, não um SSLContext. Estou esquecendo de algo?
MSpeed
2
Recebo o erro de que um X509TrustManager não pode ser convertido em um TrustManager.
MW.
2
Certifique-se de importar os pacotes corretos, ou seja, do org.apache.http.
diretor
2
Alguém sabe como juntar tudo isso usando HttpClientBuilder?
Ali
112
Todas as outras respostas foram preteridas ou não funcionaram no HttpClient 4.3.
Aqui está uma maneira de permitir todos os nomes de host ao criar um cliente http.
Obrigado pela resposta, gostaria de saber de qual pacote HttpsClients estou usando na compilação do Android ("org.apache.httpcomponents: httpclient: 4.3.4"), mas essa classe não aparece.
Juan Saravia
1
Seu pacote é org.apache.http.impl.client.HttpClients.
2171414
14
Isso funciona em torno de uma incompatibilidade de nome de host (suponho), mas parece não funcionar quando o certificado não é assinado por uma autoridade confiável.
Twm
1
@twm é por isso que diz que "permite todos os nomes de host", os problemas de confiança exigem uma configuração diferente.
eis
1
@eis, eu estava apontando que esta resposta aborda a pergunta original em certos casos, mas não em outros.
Twm
43
Só tive que fazer isso com o HttpClient 4.5 mais recente e parece que eles preteriram algumas coisas desde o 4.4. Aqui está o snippet que funciona para mim e usa a API mais recente:
Obrigado! Apenas mude TrustAllStrategy.INSTANCEcom TrustSelfSignedStrategy.INSTANCEnesta resposta.
Percy Vega
Isto não funcionou para mim. javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: falha na construção do caminho PKIX: sun.security. provider.certpath.SunCertPathBuilderException: não foi possível encontrar o caminho de certificação válido para o destino solicitado
ggb667 22/06
26
Para o registro, testado com o httpclient 4.3.6 e compatível com o Executor de API fluente:
Para o HttpClient 4.4 em diante, é necessário fazer isso - e também pode ser necessário criar um SSLConnectionSocketFactoryuso disso SSLContexte defini-lo em a Registry<ConnectionSocketFactory>, se você for criar um PoolingHttpClientConnectionManager. As outras respostas são mais populares, mas não funcionam no HttpClient 4.4.
21415 Thomas Thomas W
1
Funciona exatamente assim com httpclient-4.3.5.jar.
Harald
18
Para o Apache HttpClient 4.4:
HttpClientBuilder b =HttpClientBuilder.create();SSLContext sslContext =newSSLContextBuilder().loadTrustMaterial(null,newTrustStrategy(){publicboolean isTrusted(X509Certificate[] arg0,String arg1)throwsCertificateException{returntrue;}}).build();
b.setSslcontext( sslContext);// or SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if you don't want to weakenHostnameVerifier hostnameVerifier =SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;SSLConnectionSocketFactory sslSocketFactory =newSSLConnectionSocketFactory(sslContext, hostnameVerifier);Registry<ConnectionSocketFactory> socketFactoryRegistry =RegistryBuilder.<ConnectionSocketFactory>create().register("http",PlainConnectionSocketFactory.getSocketFactory()).register("https", sslSocketFactory).build();// allows multi-threaded usePoolingHttpClientConnectionManager connMgr =newPoolingHttpClientConnectionManager( socketFactoryRegistry);
b.setConnectionManager( connMgr);HttpClient client = b.build();
Isso é extraído de nossa implementação de trabalho real.
As outras respostas são populares, mas para o HttpClient 4.4 elas não funcionam. Passei horas tentando e esgotando as possibilidades, mas parece ter havido mudanças e realocações extremamente importantes na API no 4.4.
O método sf.setHostnameVerifier foi descontinuado a partir do 4.1. A alternativa é usar um dos construtores. Por exemplo:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech
Isso foi muito útil quando tive que lidar com código legado.
precisa saber é o seguinte
9
Estamos usando o HTTPClient 4.3.5 e tentamos quase todas as soluções existentes no stackoverflow, mas nada. Depois de pensar e descobrir o problema, chegamos ao código a seguir que funciona perfeitamente, basta adicioná-lo antes de criar a instância HttpClient.
algum método para chamar ao fazer solicitações de postagem ....
Você pode conseguir o mesmo fazendo #sf.setHostnameVerifier(new AllowAllHostnameVerifier());
Dan Dyer
7
O sf.setHostnameVerifier foi descontinuado a partir do 4.1. A alternativa é usar um dos construtores. Por exemplo:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech
4
DefaultHttpClient httpclient =newDefaultHttpClient();SSLContext sslContext;try{
sslContext =SSLContext.getInstance("SSL");// set up a TrustManager that trusts everythingtry{
sslContext.init(null,newTrustManager[]{new X509TrustManager(){public X509Certificate[] getAcceptedIssuers(){
log.debug("getAcceptedIssuers =============");returnnull;}publicvoid checkClientTrusted(
X509Certificate[] certs,String authType){
log.debug("checkClientTrusted =============");}publicvoid checkServerTrusted(
X509Certificate[] certs,String authType){
log.debug("checkServerTrusted =============");}}},newSecureRandom());}catch(KeyManagementException e){}SSLSocketFactory ssf =newSSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);ClientConnectionManager ccm =this.httpclient.getConnectionManager();SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(newScheme("https",443, ssf));}catch(Exception e){
log.error(e.getMessage(),e);}
Estou recebendo o seguinte: Causado por: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Nenhum nome alternativo de assunto está presente?
Como permitir conexões a sites SSL sem certs na API HttpClient ou na API RestClient?
4
Testado com o HttpClient 4.5.5 com API fluente
finalSSLContext sslContext =newSSLContextBuilder().loadTrustMaterial(null,(x509CertChain, authType)->true).build();CloseableHttpClient httpClient =HttpClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).setSSLContext(sslContext).build();String result =Executor.newInstance(httpClient).execute(Request.Get("https://localhost:8080/someapi").connectTimeout(1000).socketTimeout(1000)).returnContent().asString();
obrigado pela resposta atualizada, concedi a recompensa ao novo cara por ser "acolhedor", mas eu só queria respostas atualizadas para todos!
1
@feelingunwelcome, com certeza. Também votei nele :-)
Tarun Lalwani
2
uma versão de trabalho completa do Apache HttpClient 4.1.3 (com base no código da oleg acima, mas ele ainda precisava de um allow_all_hostname_verifier no meu sistema):
Se você encontrou esse problema ao usar o AmazonS3Client, que incorpora o Apache HttpClient 4.1, basta definir uma propriedade do sistema como esta para que o verificador de certificado SSL seja relaxado:
Se você estiver usando o Apache httpClient 4.5.x , tente o seguinte:
publicstaticvoid main(String... args){try(CloseableHttpClient httpclient = createAcceptSelfSignedCertificateClient()){HttpGet httpget =newHttpGet("https://example.com");System.out.println("Executing request "+ httpget.getRequestLine());
httpclient.execute(httpget);System.out.println("----------------------------------------");}catch(NoSuchAlgorithmException|KeyStoreException|KeyManagementException|IOException e){thrownewRuntimeException(e);}}privatestaticCloseableHttpClient createAcceptSelfSignedCertificateClient()throwsKeyManagementException,NoSuchAlgorithmException,KeyStoreException{// use the TrustSelfSignedStrategy to allow Self Signed CertificatesSSLContext sslContext =SSLContextBuilder.create().loadTrustMaterial(newTrustSelfSignedStrategy()).build();// we can optionally disable hostname verification. // if you don't want to further weaken the security, you don't have to include this.HostnameVerifier allowAllHosts =newNoopHostnameVerifier();// create an SSL Socket Factory to use the SSLContext with the trust self signed certificate strategy// and allow all hosts verifier.SSLConnectionSocketFactory connectionFactory =newSSLConnectionSocketFactory(sslContext, allowAllHosts);// finally create the HttpClient using HttpClient factory methods and assign the ssl socket factoryreturnHttpClients.custom().setSSLSocketFactory(connectionFactory).build();}
Respostas:
Você precisa criar um SSLContext com seu próprio TrustManager e criar um esquema HTTPS usando esse contexto. Aqui está o código,
fonte
HttpClientBuilder
?Todas as outras respostas foram preteridas ou não funcionaram no HttpClient 4.3.
Aqui está uma maneira de permitir todos os nomes de host ao criar um cliente http.
Ou, se você estiver usando a versão 4.4 ou posterior, a chamada atualizada será semelhante a:
fonte
Só tive que fazer isso com o HttpClient 4.5 mais recente e parece que eles preteriram algumas coisas desde o 4.4. Aqui está o snippet que funciona para mim e usa a API mais recente:
fonte
Apenas para constar, há uma maneira muito mais simples de fazer o mesmo com o HttpClient 4.1
fonte
new SSLSocketFactory((chain, authType) -> true);
Apache HttpClient 4.5.5
Nenhuma API descontinuada foi usada.
Caso de teste verificável simples:
fonte
TrustAllStrategy.INSTANCE
comTrustSelfSignedStrategy.INSTANCE
nesta resposta.Para o registro, testado com o httpclient 4.3.6 e compatível com o Executor de API fluente:
fonte
SSLConnectionSocketFactory
uso dissoSSLContext
e defini-lo em aRegistry<ConnectionSocketFactory>
, se você for criar umPoolingHttpClientConnectionManager
. As outras respostas são mais populares, mas não funcionam no HttpClient 4.4.Para o Apache HttpClient 4.4:
Isso é extraído de nossa implementação de trabalho real.
As outras respostas são populares, mas para o HttpClient 4.4 elas não funcionam. Passei horas tentando e esgotando as possibilidades, mas parece ter havido mudanças e realocações extremamente importantes na API no 4.4.
Veja também uma explicação um pouco mais completa em: http://literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/
Espero que ajude!
fonte
Se tudo o que você deseja fazer é se livrar de erros de nome de host inválidos, basta:
fonte
SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Estamos usando o HTTPClient 4.3.5 e tentamos quase todas as soluções existentes no stackoverflow, mas nada. Depois de pensar e descobrir o problema, chegamos ao código a seguir que funciona perfeitamente, basta adicioná-lo antes de criar a instância HttpClient.
fonte
Com 4.5.2 fluente, tive que fazer a seguinte modificação para fazê-lo funcionar.
fonte
Foi assim que eu fiz -
Inicializando DefaultHTTPClient -
Mock SSL Factory -
Se estiver atrás de um proxy, precisa fazer isso -
fonte
Em extensão à resposta do ZZ Coder , será bom substituir o hostnameverifier.
fonte
sf.setHostnameVerifier(new AllowAllHostnameVerifier());
SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
fonte
Para aceitar todos os certificados no HttpClient 4.4.x, você pode usar o seguinte liner ao criar o httpClient:
fonte
Testado com o HttpClient 4.5.5 com API fluente
fonte
O código abaixo funciona com
4.5.5
A saída do código é
A saída no navegador é
O pom usado está abaixo
fonte
uma versão de trabalho completa do Apache HttpClient 4.1.3 (com base no código da oleg acima, mas ele ainda precisava de um allow_all_hostname_verifier no meu sistema):
Observe que estou lançando todas as exceções porque, na verdade, não há muito que eu possa fazer se algo disso falhar em um sistema real!
fonte
Se você estiver usando a API fluente , precisará configurá-la através do
Executor
:... onde
sslContext
é criado o SSLContext, como mostrado na resposta do codificador ZZ .Depois disso, você pode fazer suas solicitações http como:
Nota: testado com HttpClient 4.2
fonte
Testado com 4.3.3
}
fonte
Testado em 4.5.4:
fonte
Se você encontrou esse problema ao usar o AmazonS3Client, que incorpora o Apache HttpClient 4.1, basta definir uma propriedade do sistema como esta para que o verificador de certificado SSL seja relaxado:
-Dcom.amazonaws.sdk.disableCertChecking = true
Malícia gerenciada
fonte
fwiw, um exemplo usando a implementação "RestEasy" do JAX-RS 2.x para criar um cliente especial "trust all" ...
dependências relacionadas ao Maven
fonte
Se você estiver usando o Apache httpClient 4.5.x , tente o seguinte:
fonte