Estou usando o Java 6 e tentando criar um HttpsURLConnection
em um servidor remoto, usando um certificado de cliente.
O servidor está usando um certificado raiz autoassinado e requer a apresentação de um certificado de cliente protegido por senha. Eu adicionei o certificado raiz do servidor e o certificado do cliente a um keystore java padrão que encontrei em /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/lib/security/cacerts
(OSX 10.5). O nome do arquivo de armazenamento de chave parece sugerir que o certificado do cliente não deve ir lá.
De qualquer forma, adicionar o certificado raiz a esta loja resolveu o infame javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed' problem.
No entanto, agora estou sem saber como usar o certificado do cliente. Tentei duas abordagens e nenhuma me levou a lugar nenhum.
Primeiro, e de preferência, tente:
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
URL url = new URL("https://somehost.dk:3049");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(sslsocketfactory);
InputStream inputstream = conn.getInputStream();
// The last line fails, and gives:
// javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
Tentei pular a classe HttpsURLConnection (não é o ideal, pois quero falar HTTP com o servidor) e, em vez disso:
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("somehost.dk", 3049);
InputStream inputstream = sslsocket.getInputStream();
// do anything with the inputstream results in:
// java.net.SocketTimeoutException: Read timed out
Eu nem tenho certeza se o certificado do cliente é o problema aqui.
Respostas:
Finalmente resolvi;). Tenho uma dica forte aqui (a resposta de Gandalf também tocou um pouco nisso). Os links ausentes eram (principalmente) o primeiro dos parâmetros abaixo e, até certo ponto, esqueci a diferença entre keystores e truststores.
O certificado do servidor autoassinado deve ser importado para um armazenamento confiável:
Essas propriedades precisam ser definidas (na linha de comando ou no código):
Código de exemplo de trabalho:
fonte
Embora não seja recomendado, você também pode desativar a validação do certificado SSL por completo:
fonte
Você definiu as propriedades do sistema KeyStore e / ou TrustStore?
ou de com o código
Mesmo com javax.net.ssl.trustStore
fonte
Se você estiver lidando com uma chamada de serviço da Web usando a estrutura Axis, há uma resposta muito mais simples. Se tudo que você deseja é que seu cliente possa chamar o serviço da web SSL e ignorar os erros do certificado SSL, basta colocar esta instrução antes de invocar qualquer serviço da web:
System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");
As isenções de responsabilidade usuais sobre isso ser uma coisa muito ruim de se fazer em um ambiente de produção se aplicam.
Eu encontrei isso no wiki do Axis .
fonte
Para mim, isso é o que funcionou usando Apache HttpComponents ~ HttpClient 4.x:
O arquivo P12 contém o certificado do cliente e a chave privada do cliente, criado com BouncyCastle:
fonte
keyStore
é o que contém a chave privada e certificado.Eu uso o pacote do cliente HTTP Apache commons para fazer isso no meu projeto atual e ele funciona bem com SSL e um certificado autoassinado (após instalá-lo em cacerts como você mencionou). Por favor, dê uma olhada nele:
http://hc.apache.org/httpclient-3.x/tutorial.html
http://hc.apache.org/httpclient-3.x/sslguide.html
fonte
SSLContext
diretamente, então você pode configurar tudo dessa forma, em vez de usarAuthSSLProtocolSocketFactory
.Acho que você tem um problema com o certificado do servidor, não é um certificado válido (acho que é isso que "handshake_failure" significa neste caso):
Importe o certificado do servidor para o armazenamento de chaves trustcacerts no JRE do cliente. Isso é feito facilmente com o keytool :
fonte
Usando o código abaixo
ou
não é necessário. Além disso, não há necessidade de criar sua própria fábrica SSL personalizada.
Eu também encontrei o mesmo problema, no meu caso, houve um problema que a cadeia de certificação completa não foi importada para armazenamentos confiáveis. Importe certificados usando o utilitário keytool diretamente do certificado raiz, você também pode abrir o arquivo cacerts no bloco de notas e ver se a cadeia de certificados completa é importada ou não. Verifique o nome alternativo que você forneceu ao importar certificados, abra os certificados e veja quantos ele contém; o mesmo número de certificados deve estar no arquivo cacerts.
Além disso, o arquivo cacerts deve ser configurado no servidor em que você está executando o aplicativo, os dois servidores se autenticarão com chaves públicas / privadas.
fonte