Java: sun.security.provider.certpath.SunCertPathBuilderException: não foi possível encontrar o caminho de certificação válido para o destino solicitado


248

Eu tenho uma classe que baixará um arquivo de um servidor https . Quando eu o executo, ele retorna muitos erros. Parece que tenho um problema com meu certificado. É possível ignorar a autenticação cliente-servidor? Se sim, como?

package com.da;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.concurrent.Future;

import org.apache.http.HttpResponse;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
import org.apache.http.nio.IOControl;
import org.apache.http.nio.client.HttpAsyncClient;
import org.apache.http.nio.client.methods.AsyncCharConsumer;
import org.apache.http.nio.client.methods.HttpAsyncGet;
import org.apache.http.nio.client.methods.HttpAsyncPost;

public class RSDDownloadFile {
    static FileOutputStream fos;

    public void DownloadFile(String URI, String Request) throws Exception
    {
        java.net.URI uri = URIUtils.createURI("https", "176.66.3.69:6443", -1, "download.aspx",
                "Lang=EN&AuthToken=package", null);
        System.out.println("URI Query: " + uri.toString());

        HttpAsyncClient httpclient = new DefaultHttpAsyncClient();
        httpclient.start();
        try {
            Future<Boolean> future = httpclient.execute(
                    new HttpAsyncGet(uri),
                    new ResponseCallback(), null);

            Boolean result = future.get();
            if (result != null && result.booleanValue()) {
                System.out.println("\nRequest successfully executed");
            } else {
                System.out.println("Request failed");
            }              
        } 
        catch(Exception e){
            System.out.println("[DownloadFile] Exception: " + e.getMessage());
        }
        finally {
            System.out.println("Shutting down");
            httpclient.shutdown();
        }
        System.out.println("Done");  

    }

    static class ResponseCallback extends AsyncCharConsumer<Boolean> {

        @Override
        protected void onResponseReceived(final HttpResponse response) {
             System.out.println("Response: " + response.getStatusLine());
             System.out.println("Header: " + response.toString());
             try {   
                 //if(response.getStatusLine().getStatusCode()==200)
                     fos = new FileOutputStream( "Response.html" );
             }catch(Exception e){
                 System.out.println("[onResponseReceived] Exception: " + e.getMessage());
             }
        }

        @Override
        protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException {
            try
            {
                while (buf.hasRemaining()) 
                {
                    //System.out.print(buf.get());
                    fos.write(buf.get());
                }
            }catch(Exception e)
            {
                System.out.println("[onCharReceived] Exception: " + e.getMessage());
            }
        }

        @Override
        protected void onCleanup() {
            try
            {             
                if(fos!=null)
                    fos.close();
            }catch(Exception e){
                System.out.println("[onCleanup] Exception: " + e.getMessage());         
            }
             System.out.println("onCleanup()");
        }

        @Override
        protected Boolean buildResult() {
            return Boolean.TRUE;
        }

    }
}

Erros:

URI Query: https://176.66.3.69:6443/download.aspx?Lang=EN&AuthToken=package
Aug 2, 2011 3:47:57 PM org.apache.http.impl.nio.client.NHttpClientProtocolHandler exception
SEVERE: I/O error: General SSLEngine problem
javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.writeAppRecord(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.wrap(Unknown Source)
    at javax.net.ssl.SSLEngine.wrap(Unknown Source)
    at org.apache.http.impl.nio.reactor.SSLIOSession.doHandshake(SSLIOSession.java:154)
    at org.apache.http.impl.nio.reactor.SSLIOSession.isAppInputReady(SSLIOSession.java:276)
    at org.apache.http.impl.nio.client.InternalClientEventDispatch.inputReady(InternalClientEventDispatch.java:79)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:161)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:335)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:275)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
    at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:542)
    at java.lang.Thread.run(Unknown Source)
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.net.ssl.internal.ssl.Handshaker$DelegatedTask.run(Unknown Source)
    at org.apache.http.impl.nio.reactor.SSLIOSession.doHandshake(SSLIOSession.java:180)
    ... 9 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
    at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
    at sun.security.validator.Validator.validate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(Unknown Source)
    ... 16 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
    at java.security.cert.CertPathBuilder.build(Unknown Source)
    ... 21 more
onCleanup()

[DownloadFile] Exception: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
Shutting down
Done

2
Uma vez, recebi esse erro e entrei em contato com nossa equipe de segurança, e tive que corrigir o JAR que estávamos usando, pois nossa equipe estava usando um desatualizado fornecido pela empresa. Apenas um FYI para qualquer pessoa que possa estar em uma situação semelhante.
kayleeFrye_onDeck

Respostas:


215

O problema aparece quando o servidor possui certificado autoassinado. Para solucionar esse problema, você pode adicionar este certificado à lista de certificados confiáveis ​​da sua JVM.

Neste artigo, o autor descreve como buscar o certificado do seu navegador e adicioná-lo ao arquivo cacerts da sua JVM. Você pode editar o JAVA_HOME/jre/lib/security/cacertsarquivo ou executar seu aplicativo com o -Djavax.net.ssl.trustStoreparâmetro Verifique também qual JDK / JRE você está usando, pois isso geralmente é uma fonte de confusão.

Consulte também: Como os nomes dos servidores de certificados SSL são resolvidos / Posso adicionar nomes alternativos usando o keytool? Se você encontrar uma java.security.cert.CertificateException: No name matching localhost foundexceção.


3
isso não funcionou para mim. Eu tenho o certificado raiz e de cadeia instalado, mas o Tomcat-7 ainda relata validatorException causada por "não foi possível encontrar o caminho de certificação válido para o destino solicitado" de alguma maneira para depurar isso?
Cheruvim 20/05

O problema também aparece com um certificado assinado por outra pessoa que não é confiável.
Marquês de Lorne

Ótimo! Funciona! Só não esqueça que você poderia ter o jre e o jdk, e os dois cacertsdevem ser atualizados
Dima Fomin

No meu caso, a CA raiz estava lá, mas não a próxima CA inativa. Adicionar a próxima CA desativada fez o truque - obrigado.
Java-addict301

1
No meu caso, estou usando o Netbeans + Apache Tomcat (integrado), adicionando .cer ao armazenamento confiável "cacerts" no Jdk / jre (C: \ Arquivos de Programas \ Java \ jdk1.8.0_152 \ jre \ lib \ segurança) e Jre (C: \ Arquivos de programas \ Java \ jre1.8.0_91 \ lib \ security) funciona para mim
Jnn

149

Aqui está o que funciona de maneira confiável para mim no macOS. Substitua example.com e 443 pelo nome do host e porta reais aos quais você está tentando se conectar e forneça um alias personalizado. O primeiro comando baixa o certificado fornecido do servidor remoto e o salva localmente no formato x509. O segundo comando carrega o certificado salvo no armazenamento confiável SSL do Java.

openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2>/dev/null) -out ~/example.crt
sudo keytool -importcert -file ~/example.crt -alias example -keystore $(/usr/libexec/java_home)/jre/lib/security/cacerts -storepass changeit

3
Funciona para mim porque? Você precisa fornecer uma explicação.
Marquês de Lorne

openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2> / dev / null) -out ~ / example.crt - o que é exemplo.crt no comando eu tenho um certificado .pem que preciso fornecer isso aqui ??
Vishnu Ranganathan

3
.crt e .pem são extensões de arquivo comumente usadas para o mesmo formato de arquivo. Se você já possui o arquivo, basta executar o segundo comando e passá-lo para o argumento -file.
Gabe Martin-Dempesy

1
Coisas boas. A única coisa é: eu tive que usar o mais recente openssl 1.0.Xx por algum motivo, o velho 9.X.Xx não estava funcionando.
zbstof

1
Isso não funciona com o ponto de extremidade SNI. Para esse caso você precisa adicionar: -servername example.com ao buscar o cert
Patrik Beck

46

Eu tive o mesmo problema com um certificado curinga assinado válido da symantec.

Primeiro, tente executar seu aplicativo java com -Djavax.net.debug = SSL para ver o que realmente está acontecendo.

Acabei importando o certificado intermediário que estava causando a quebra da cadeia de certificação .

Fiz o download do certificado intermediário ausente da symantec (você pode ver o link para o certificado ausente no log de handshake ssl: http://svrintl-g3-aia.verisign.com/SVRIntlG3.cer no meu caso).

E eu importei o certificado no keystore java. Após importar o certificado intermediário, meu certificado curinga ssl finalmente começou a funcionar:

keytool -import -keystore ../jre/lib/security/cacerts -trustcacerts -alias "VeriSign Class 3 International Server CA - G3" -file /pathto/SVRIntlG3.cer

Este foi o caso:
kisna 4/17/17

2
Para evitar confusão, execute java (ou jcurl) com parâmetros de depuração para ver a "cadeia de certificados" remota nos logs e, em seguida, cumprimente o "CN" no armazenamento confiável transmitido explicitamente (em vez do padrão) da seguinte maneira, se não estiver presente, é necessário adicionar. ssllabs.com/ssltest/analyze.html mostrará se os certificados do servidor têm uma cadeia incompleta e inclui certificados de caminho de certificação intermediários que precisam ser adicionados. -Djavax.net.debug=ssl,handshake -Djavax.net.ssl.keyStoreType=PKCS12 -Djavax.net.ssl.keyStore=our-client-certs -Djavax.net.ssl.trustStoreType=jks -Djavax.net.ssl.trustStore=their-server-certs
Kisna


Eu tive o mesmo problema, isso é muito útil, mas no meu caso só teve que adicionar o certificado de servidor para o arquivo cacerts da versão JDK
pigritia

41
  1. Exporte o certificado SSL usando o Firefox. Você pode exportá-lo pressionando o URL no navegador e, em seguida, selecione a opção para exportar o certificado. Vamos supor que o nome do arquivo cert seja your.ssl.server.name.crt
  2. Vá para o seu JRE_HOME/binouJDK/JRE/bin
  3. Digite o comando
  4. keytool -keystore ..\lib\security\cacerts -import -alias your.ssl.server.name -file .\relative-path-to-cert-file\your.ssl.server.name.crt
  5. Reinicie seu processo Java

13
Se for solicitada uma senha, use a senha padrão do keystore cacerts changeit( stackoverflow.com/a/22782035/1304830 ). Certifique-se também de executar o cmd como administrador.
Fr4nz

22

A resposta de @Gabe Martin-Dempesy é ajudada para mim. E eu escrevi um pequeno script relacionado a ele. O uso é muito simples.

Instale um certificado do host:

> sudo ./java-cert-importer.sh example.com

Remova o certificado que já está instalado.

> sudo ./java-cert-importer.sh example.com --delete

java-cert-importer.sh

#!/usr/bin/env bash

# Exit on error
set -e

# Ensure script is running as root
if [ "$EUID" -ne 0 ]
  then echo "WARN: Please run as root (sudo)"
  exit 1
fi

# Check required commands
command -v openssl >/dev/null 2>&1 || { echo "Required command 'openssl' not installed. Aborting." >&2; exit 1; }
command -v keytool >/dev/null 2>&1 || { echo "Required command 'keytool' not installed. Aborting." >&2; exit 1; }

# Get command line args
host=$1; port=${2:-443}; deleteCmd=${3:-${2}}

# Check host argument
if [ ! ${host} ]; then
cat << EOF
Please enter required parameter(s)

usage:  ./java-cert-importer.sh <host> [ <port> | default=443 ] [ -d | --delete ]

EOF
exit 1
fi;

if [ "$JAVA_HOME" ]; then
    javahome=${JAVA_HOME}
elif [[ "$OSTYPE" == "linux-gnu" ]]; then # Linux
    javahome=$(readlink -f $(which java) | sed "s:bin/java::")
elif [[ "$OSTYPE" == "darwin"* ]]; then # Mac OS X
    javahome="$(/usr/libexec/java_home)/jre"
fi

if [ ! "$javahome" ]; then
    echo "WARN: Java home cannot be found."
    exit 1
elif [ ! -d "$javahome" ]; then
    echo "WARN: Detected Java home does not exists: $javahome"
    exit 1
fi

echo "Detected Java Home: $javahome"

# Set cacerts file path
cacertspath=${javahome}/lib/security/cacerts
cacertsbackup="${cacertspath}.$$.backup"

if ( [ "$deleteCmd" == "-d" ] || [ "$deleteCmd" == "--delete" ] ); then
    sudo keytool -delete -alias ${host} -keystore ${cacertspath} -storepass changeit
    echo "Certificate is deleted for ${host}"
    exit 0
fi

# Get host info from user
#read -p "Enter server host (E.g. example.com) : " host
#read -p "Enter server port (Default 443) : " port

# create temp file
tmpfile="/tmp/${host}.$$.crt"

# Create java cacerts backup file
cp ${cacertspath} ${cacertsbackup}

echo "Java CaCerts Backup: ${cacertsbackup}"

# Get certificate from speficied host
openssl x509 -in <(openssl s_client -connect ${host}:${port} -prexit 2>/dev/null) -out ${tmpfile}

# Import certificate into java cacerts file
sudo keytool -importcert -file ${tmpfile} -alias ${host} -keystore ${cacertspath} -storepass changeit

# Remove temp certificate file
rm ${tmpfile}

# Check certificate alias name (same with host) that imported successfully
result=$(keytool -list -v -keystore ${cacertspath} -storepass changeit | grep "Alias name: ${host}")

# Show results to user
if [ "$result" ]; then
    echo "Success: Certificate is imported to java cacerts for ${host}";
else
    echo "Error: Something went wrong";
fi;

Funciona perfeitamente. Bom trabalho! . É assim que funciona: inicie o serviço SSL (se não estiver em execução) e execute o comando conforme explicado (por exemplo ./java-cert-importer.sh example.com 1234). É isso aí.
Lepe

1
Funciona bem. Eu estava recebendo o erro em um servidor Jenkins se conectando a uma API externa que altera seu certificado e falha nos meus builts. Isso resolve meu problema
user9869932 10/10

A Oracle deveria ter fornecido algo assim em primeiro lugar ou nunca todos criaram sua própria solução SSL horrível. A manipulação de certificados SSL deve ser uma tarefa do sistema operacional.
Wolfgang Fahl

17

Citação de No more 'incapaz de encontrar o caminho de certificação válido para o destino solicitado'

ao tentar abrir uma conexão SSL com um host usando JSSE. O que isso geralmente significa é que o servidor está usando um certificado de teste (possivelmente gerado usando o keytool) em vez de um certificado de uma Autoridade de Certificação comercial conhecida como Verisign ou GoDaddy. Os navegadores da Web exibem caixas de diálogo de aviso nesse caso, mas como o JSSE não pode assumir que um usuário interativo esteja presente, ele lança uma exceção por padrão.

A validação de certificado é uma parte muito importante da segurança SSL, mas não estou escrevendo esta entrada para explicar os detalhes. Se você estiver interessado, pode começar lendo o resumo da Wikipedia. Estou escrevendo esta entrada para mostrar uma maneira simples de conversar com esse host com o certificado de teste, se você realmente quiser.

Basicamente, você deseja adicionar o certificado do servidor ao KeyStore com seus certificados confiáveis

Experimente o código fornecido lá. Isso pode ajudar.


5
A parte sobre "A validação de certificado é uma parte muito importante da segurança SSL" não é necessariamente verdadeira. O SSL oferece duas garantias: (1) que sua comunicação é privada e (2) que você está conversando com um servidor conhecido pela NSA. (:-) Às vezes, você se preocupa apenas com a privacidade da conversa e, em seguida, com um certificação autoassinada está bem. Veja social-biz.org/2011/10/16/the-anti-ssl-conspiracy
AgilePro

O @AgilePro SSL oferece quatro garantias: autenticação, privacidade, integridade e a possibilidade de autorização. Ele não lhe dá qualquer garantia de que você está falando com um servidor conhecido no NSA. Importar-se apenas com privacidade sem autenticação é uma contradição em termos.
Marquês de Lorne

@EJP Concordo que, se você usar um certificado de cliente, poderá obter autenticação e suponho a possibilidade de autorização ... mas a maioria dos usos não é com um certificado de cliente. Como você chamaria a diferença entre um certificado "autoassinado" e um certificado de uma autoridade de assinatura? A autoridade de assinatura dá "integridade". Minha piada sobre a NSA é que todas as autoridades de assinatura não podem garantir positivamente a independência de tudo. Não é realmente paranóico, mas o ponto é que o seu certificado é APENAS tão secreto quanto a autoridade de assinatura pode fazer. Autoassinado pode ser mais secreto.
AgilePro 26/10/16

@AgilePro O uso de um certificado de servidor autentica o servidor e é necessário para tornar o SSL seguro, conforme observado na RFC 2246. Os certificados não são secretos: portanto, o restante do seu comentário não faz sentido.
Marquês de Lorne

6

Isso resolveu meu problema,

Precisamos importar o certificado para o java local. Caso contrário, poderíamos obter a exceção abaixo.

    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
        em sun.security.ssl.Alerts.getSSLException (Alerts.java:192)
        em sun.security.ssl.SSLSocketImpl.fatal (SSLSocketImpl.java:1949)
        em sun.security.ssl.Handshaker.fatalSE (Handshaker.java:302)

SSLPOKE é uma ferramenta na qual você pode testar a conectividade https na sua máquina local.

Comando para testar a conectividade:

"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
    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
        em sun.security.validator.PKIXValidator.doBuild (PKIXValidator.java:387)
        em sun.security.validator.PKIXValidator.engineValidate (PKIXValidator.java:292)
        em sun.security.validator.Validator.validate (Validator.java:260)
        em sun.security.ssl.X509TrustManagerImpl.validate (X509TrustManagerImpl.java:324)
        em sun.security.ssl.X509TrustManagerImpl.checkTrusted (X509TrustManagerImpl.java:229)
        em sun.security.ssl.X509TrustManagerImpl.checkServerTrusted (X509TrustManagerImpl.java:124)
        em sun.security.ssl.ClientHandshaker.serverCertificate (ClientHandshaker.java:1496)
        em sun.security.ssl.ClientHandshaker.processMessage (ClientHandshaker.java:216)
        em sun.security.ssl.Handshaker.processLoop (Handshaker.java:1026)
        em sun.security.ssl.Handshaker.process_record (Handshaker.java:961)
        em sun.security.ssl.SSLSocketImpl.readRecord (SSLSocketImpl.java:1062)
        em sun.security.ssl.SSLSocketImpl.performInitialHandshake (SSLSocketImpl.java:1375)
        em sun.security.ssl.SSLSocketImpl.writeRecord (SSLSocketImpl.java:747)
        em sun.security.ssl.AppOutputStream.write (AppOutputStream.java:123)
        em sun.security.ssl.AppOutputStream.write (AppOutputStream.java:138)
        em SSLPoke.main (SSLPoke.java:31)
    Causado por: sun.security.provider.certpath.SunCertPathBuilderException: não foi possível encontrar o caminho de certificação válido para 
    alvo solicitado
        em sun.security.provider.certpath.SunCertPathBuilder.build (SunCertPathBuilder.java:141)
        em sun.security.provider.certpath.SunCertPathBuilder.engineBuild (SunCertPathBuilder.java:126)
        em java.security.cert.CertPathBuilder.build (CertPathBuilder.java:280)
        em sun.security.validator.PKIXValidator.doBuild (PKIXValidator.java:382)
        ... mais 15
keytool -import -alias <anyname> -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file <cert path>

isso solicitaria primeiro "Digite a senha do keystore:" changeité a senha padrão. e, finalmente, um prompt "Confiar neste certificado? [não]:", forneça "yes" para adicionar o certificado ao keystore.

Verficação:

C:\tools>"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
Successfully connected    

5

Consegui fazê-lo funcionar apenas com código, ou seja, não há necessidade de usar o keytool:

import com.netflix.config.DynamicBooleanProperty;
import com.netflix.config.DynamicIntProperty;
import com.netflix.config.DynamicPropertyFactory;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.conn.NoopIOSessionStrategy;
import org.apache.http.nio.conn.SchemeIOSessionStrategy;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class Test
{
    private static final DynamicIntProperty MAX_TOTAL_CONNECTIONS = DynamicPropertyFactory.getInstance().getIntProperty("X.total.connections", 40);
    private static final DynamicIntProperty ROUTE_CONNECTIONS = DynamicPropertyFactory.getInstance().getIntProperty("X.total.connections", 40);
    private static final DynamicIntProperty CONNECT_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.connect.timeout", 60000);
    private static final DynamicIntProperty SOCKET_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.socket.timeout", -1);
    private static final DynamicIntProperty CONNECTION_REQUEST_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.connectionrequest.timeout", 60000);
    private static final DynamicBooleanProperty STALE_CONNECTION_CHECK = DynamicPropertyFactory.getInstance().getBooleanProperty("X.checkconnection", true);

    public static void main(String[] args) throws Exception
    {

        SSLContext sslcontext = SSLContexts.custom()
                .useTLS()
                .loadTrustMaterial(null, new TrustStrategy()
                {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException
                    {
                        return true;
                    }
                })
                .build();
        SSLIOSessionStrategy sslSessionStrategy = new SSLIOSessionStrategy(sslcontext, new AllowAll());

        Registry<SchemeIOSessionStrategy> sessionStrategyRegistry = RegistryBuilder.<SchemeIOSessionStrategy>create()
                .register("http", NoopIOSessionStrategy.INSTANCE)
                .register("https", sslSessionStrategy)
                .build();

        DefaultConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(IOReactorConfig.DEFAULT);
        PoolingNHttpClientConnectionManager connectionManager = new PoolingNHttpClientConnectionManager(ioReactor, sessionStrategyRegistry);
        connectionManager.setMaxTotal(MAX_TOTAL_CONNECTIONS.get());
        connectionManager.setDefaultMaxPerRoute(ROUTE_CONNECTIONS.get());

        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(SOCKET_TIMEOUT.get())
                .setConnectTimeout(CONNECT_TIMEOUT.get())
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT.get())
                .setStaleConnectionCheckEnabled(STALE_CONNECTION_CHECK.get())
                .build();

        CloseableHttpAsyncClient httpClient = HttpAsyncClients.custom()
                .setSSLStrategy(sslSessionStrategy)
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(requestConfig)
                .build();

        httpClient.start();

        // use httpClient...
    }

    private static class AllowAll implements X509HostnameVerifier
    {
        @Override
        public void verify(String s, SSLSocket sslSocket) throws IOException
        {}

        @Override
        public void verify(String s, X509Certificate x509Certificate) throws SSLException {}

        @Override
        public void verify(String s, String[] strings, String[] strings2) throws SSLException
        {}

        @Override
        public boolean verify(String s, SSLSession sslSession)
        {
            return true;
        }
    }
}

1
Btw, eu estou usando httpasyncclient: 4.0.1
Jonas Bergström

Eu precisava de algo semelhante, @ JonasBergström, sua solução com o SSLContext ajuda muito.
precisa

8
Observe que esta solução é insegura.
Marquês de Lorne

Obrigado Jonas, sua solução resolveu o problema. Mas eu achei que custa muito tempo (3 - 5s) para criar a primeira conexão, depois disso toda conexão precisa apenas de 300 a 400 ms.
twcai

5

A origem desse erro na minha instância do Apache 2.4 (usando um certificado curinga Comodo) era um caminho incompleto para o certificado raiz assinado SHA-1. Havia várias cadeias no certificado emitido e a cadeia que levava a um certificado raiz SHA-1 estava sem um certificado intermediário . Navegadores modernos sabem como lidar com isso, mas o Java 7 não o trata por padrão (embora existam algumas maneiras complicadas de fazer isso no código). O resultado são mensagens de erro que parecem idênticas ao caso de certificados autoassinados:

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
    ... 22 more

Nesse caso, a mensagem "não é possível encontrar o caminho de certificação válido para o destino solicitado" está sendo produzida devido à falta do certificado intermediário. Você pode verificar qual certificado está ausente usando o SSL Labs teste no servidor. Depois de encontrar o certificado apropriado, faça o download e (se o servidor estiver sob seu controle), adicione-o ao pacote de certificados. Como alternativa, você pode importar o certificado ausente localmente. Acomodar esse problema no servidor é uma solução mais geral para o problema.


ssllabs.com/ssltest é um salvador, basta compará-lo com uma validação de certificado de trabalho.
Kisna # 26/16

5

Somente para Windows, siga estas etapas:

  1. No Chrome, vá para configurações.
  2. Em Configurações, clique em mostrar configurações avançadas.
  3. Em HTTPS / SSL, clique em Gerenciar certificados.
  4. Exporte seu certificado.
  5. Nas pesquisas do Windows (pressionando a tecla Windows no teclado), digite java.
  6. Selecione a opção (Configurar Java) que abrirá o Painel de controle Java
  7. Selecione a guia Segurança no Painel de Controle Java
  8. Selecione Gerenciar certificados
  9. Clique em Importar
  10. Na guia (Usuário) selecionada e tipo de certificado como (Certificados confiáveis)
  11. Clique no botão Importar e navegue até o certificado baixado e importe-o.

4

Para quem gosta de Debian e Java pré-empacotado:

sudo mkdir /usr/share/ca-certificates/test/  # don't mess with other certs
sudo cp ~/tmp/test.loc.crt /usr/share/ca-certificates/test/
sudo dpkg-reconfigure --force ca-certificates  # check your cert in curses GUI!
sudo update-ca-certificates --fresh --verbose

Não se esqueça de verificar /etc/default/cacerts:

# enable/disable updates of the keystore /etc/ssl/certs/java/cacerts
cacerts_updates=yes

Para remover o cert:

sudo rm /usr/share/ca-certificates/test/test.loc.crt
sudo rm /etc/ssl/certs/java/cacerts
sudo update-ca-certificates --fresh --verbose

2

Isso também pode ser causado pelo uso de certificados GoDaddy com Java 7 assinados usando SHA2.

O Chrome e todos os outros navegadores estão começando a descontinuar certificados SSL assinados usando o SHA1, pois não é tão seguro.

Mais informações sobre o problema podem ser encontradas aqui , além de como resolvê-lo em seu servidor, se você precisar agora.


2

Eu tive o mesmo problema com o erro de certificados e foi por causa do SNI, e o cliente http que eu usei não teve o SNI implementado. Então, uma atualização de versão fez o trabalho

   <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.3.6</version>
    </dependency>

2

ATUALIZAÇÃO: Que uma reinicialização ajudou foi coincidência (eu esperava, hooray!). A verdadeira causa do problema foi a seguinte: quando o Gradle é direcionado para usar um keystore específico, esse keystore também deve conter todos os certificados raiz oficiais. Caso contrário, ele não poderá acessar bibliotecas de repositórios regulares. O que eu tinha que fazer era isso:

Importe o certificado autoassinado:

keytool -import -trustcacerts -alias myselfsignedcert -file /Users/me/Desktop/selfsignedcert.crt -keystore ./privateKeystore.jks

Adicione os certificados raiz oficiais:

keytool -importkeystore -srckeystore <java-home>/lib/security/cacerts -destkeystore ./privateKeystore.jks

Talvez o daemon Gradle também tenha atrapalhado. Pode valer a pena matar todos os daemons em execução encontrados, ./gradlew --statusse as coisas começarem a parecer sombrias.

POSTAGEM ORIGINAL:

Ninguém vai acreditar nisso, eu sei. Ainda assim, se tudo mais falhar, tente: Após a reinicialização do meu Mac, o problema desapareceu. Grrr.

Background: ./gradlew jar continuava me dando "incapaz de encontrar um caminho de certificação válido para o destino solicitado"

Estou com um certificado autoassinado, salvo no navegador, importado em privateKeystore.jks. Em seguida, instruiu Gradle a trabalhar com privateKeystore.jks:

org.gradle.jvmargs=-Djavax.net.debug=SSL -Djavax.net.ssl.trustStore="/Users/me/IntelliJ/myproject/privateKeystore.jks"  -Djavax.net.ssl.trustStorePassword=changeit

Como mencionado, isso só funcionou após uma reinicialização.


2

O AVG versão 18.1.3044 (com Windows 10) interfere no meu aplicativo local do Spring.

Solução: entre na seção AVG chamada "Web e email" e desative a "proteção de email". O AVG bloqueia o certificado se o site não for seguro.


2

Verifique se o https://176.66.3.69:6443/ possui um certificado válido. você pode verificá-lo através do navegador em primeiro lugar, https não segurose funcionar no navegador, ele funcionará em java.

isso está funcionando pra mim


E o que devo fazer se o navegador também reclamar?
The Godfather

tente instalar o certificado
Amr Ibrahim

2

Há muitas maneiras de resolver isso ...

Uma maneira é definir os certificados TrustStore em um arquivo keystore e colocá-lo no caminho do aplicativo, e definir essas propriedades do sistema no método principal:

public static void main(String[] args) {
  System.setProperty("javax.net.ssl.trustStore", "trust-store.jks");
  System.setProperty("javax.net.ssl.trustStorePassword", "TrustStore");
  ...
}

Outra maneira é colocar o keystore como arquivo de recurso dentro do arquivo jar do projeto e carregá-lo:

public static SSLContext createSSLContext(String resourcePath, String pass) throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException {
  // initialise the keystore
  final char[] password = pass.toCharArray();
  KeyStore ks = KeyStore.getInstance("JKS");
  ks.load(ThisClass.class.getResourceAsStream(resourcePath
  ), password);

  // Setup the key manager factory.
  KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
  kmf.init(ks, password);

  // Setup the trust manager factory.
  TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
  tmf.init(ks);

  SSLContext sslc = SSLContext.getInstance("TLS");
  sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  return sslc;
}

public static void main(String[] args) {
  SSLContext.setDefault(
    createSSLContext("/trust-store.jks", "TrustStore"));
  ...
}

No Windows, você também pode tentar esta solução: https://stackoverflow.com/a/59056537/980442


Criei o arquivo keystore a partir de um .crtarquivo CA da autoridade de certificação desta maneira:

keytool -import -alias ca -keystore trust-store.jks -storepass TrustStore -trustcacerts -file ca.crt

FYI: https://docs.oracle.com/javadb/10.8.3.0/adminguide/cadminsslclient.html


1

Você tem duas opções, importe o certificado autoassinado no keystore do java para cada jvm em que o software será executado ou tente a fábrica ssl não validada:

jdbc:postgresql://myserver.com:5432/mydatabasename?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory

1

Teve o problema como esta imagem.

insira a descrição da imagem aqui

Tentei algumas soluções. Mas descobriu que, mesmo que seja o mesmo projeto, quando estiver no local de trabalho de outras pessoas, está totalmente bem. Não são necessárias configurações extras. Então achamos que é uma questão ambiental. Tentamos alterar a versão do JDK, IDE, mas não funcionou. demorou cerca de 4 horas para a investigação, até tentarmos a resposta mais bem avaliada. Não encontrei o erro mencionado nessa resposta, mas descobri no meu navegador sobre o URL HTTP (bloqueio) que havia uma certificação de Charles. Então eu percebi que meu Charles estava ligado o tempo todo. Desde que eu desliguei, tudo funcionou bem.

Então, deixei minha experiência que poderia ser útil para o seu caso.


0

No meu caso, estou executando o MacOs High Sierra com Java 1.6. O arquivo cacert está em um local diferente do mencionado acima na resposta de Gabe Martin-Dempesy. O arquivo cacert também já estava vinculado a outro local (/ Library / Internet Plug-Ins / JavaAppletPlugin.plugin / Contents / Home / lib / security / cacerts).

Usando o FireFox, eu exportei o certificado do site em questão para um arquivo local chamado "exportedCertFile.crt". A partir daí, usei o keytool para mover o certificado para o arquivo cacert. Isso resolveu o problema.

bash-3.2# cd /Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/
bash-3.2# keytool -importcert -file ~/exportedCertFile.crt -alias example -keystore cacerts -storepass changeit

0

primeiro Baixe o certificado ssl e, em seguida, você pode ir para o caminho do java bin e executar o comando abaixo no console.

C:\java\JDK1.8.0_66-X64\bin>keytool -printcert -file C:\Users\lova\openapi.cer -keystore openapistore

-1

No meu caso, eu tinha o keystore e o armazenamento confiável com o mesmo certificado, portanto, a remoção do armazenamento confiável ajudou. Às vezes, a cadeia de certificados pode ser um problema se você tiver várias cópias de certificados.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.