Java:sun.security.provider.certpath.SunCertPathBuilderException:找不到请求目标的有效证书路径

Java:sun.security.provider.certpath.SunCertPathBuilderException:找不到请求目标的有效证书路径,java,ssl,https,ssl-certificate,Java,Ssl,Https,Ssl Certificate,我有一个类可以从https服务器下载文件。当我运行它时,它会返回很多错误。看来我的证书有问题。是否可以忽略客户端-服务器身份验证?如果是,怎么做 package com.da; import java.io.FileOutputStream; import java.io.IOException; import java.nio.CharBuffer; import java.util.concurrent.Future; import org.apache.http.HttpRespons

我有一个类可以从https服务器下载文件。当我运行它时,它会返回很多错误。看来我的证书有问题。是否可以忽略客户端-服务器身份验证?如果是,怎么做

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;
        }

    }
}
引用

尝试使用JSSE打开到主机的SSL连接时。这通常意味着服务器使用的是测试证书(可能使用keytool生成),而不是来自知名商业认证机构(如Verisign或GoDaddy)的证书。在这种情况下,Web浏览器会显示警告对话框,但由于JSSE不能假定存在交互用户,因此默认情况下只会抛出异常

证书验证是SSL安全性的一个非常重要的部分,但我写这篇文章不是为了解释细节。如果你感兴趣,你可以从阅读维基百科的导语开始。我写这篇文章是为了展示一种简单的方法,如果你真的想,可以用测试证书与主机对话

基本上,您希望使用受信任的证书将服务器的证书添加到密钥库中


请尝试那里提供的代码。这可能会有所帮助。

当您的服务器具有自签名证书时,问题就会出现。要解决此问题,可以将此证书添加到JVM的受信任证书列表中

作者描述了如何从浏览器中获取证书并将其添加到JVM的cacerts文件中。您可以编辑
JAVA\u HOME/jre/lib/security/cacerts
文件,也可以使用
-Djavax.net.ssl.trustStore
参数运行应用程序。验证您也在使用哪个JDK/JRE,因为这通常会引起混淆


另请参见:如果您遇到
java.security.cert.CertificateException:找不到与本地主机匹配的名称
异常。

以下是在macOS上可靠运行的方法。确保将example.com和443替换为您尝试连接的实际主机名和端口,并提供自定义别名。第一个命令从远程服务器下载提供的证书,并将其以x509格式保存在本地。第二个命令将保存的证书加载到Java的SSL信任存储中

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
javax.net.ssl.SSLHandshakeException: 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.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
opensslx509-in/dev/null)-out~/example.crt
sudo keytool-importcert-file~/example.crt-alias example-keystore$(/usr/libexec/java_home)/jre/lib/security/cacerts-storepass changeit

我在使用赛门铁克提供的有效签名通配符证书时遇到了同样的问题

首先尝试使用-Djavax.net.debug=SSL运行java应用程序,看看到底发生了什么

我最终导入了中间证书,导致证书链断裂

我从symantec下载了丢失的中间证书(您可以在ssl握手日志中看到丢失证书的下载链接:在我的例子中)

我在java密钥库中导入了证书。导入中间证书后,我的通配符ssl证书终于开始工作:

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

我能够让它只与代码一起工作,即不需要使用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;
        }
    }
}
导入com.netflix.config.DynamicBooleanProperty;
导入com.netflix.config.DynamicIntProperty;
导入com.netflix.config.DynamicPropertyFactory;
导入org.apache.http.client.config.RequestConfig;
导入org.apache.http.config.Registry;
导入org.apache.http.config.RegistryBuilder;
导入org.apache.http.conn.ssl.SSLContexts;
导入org.apache.http.conn.ssl.TrustStrategy;
导入org.apache.http.conn.ssl.X509HostnameVerifier;
导入org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
导入org.apache.http.impl.nio.client.httpacyncClients;
导入org.apache.http.impl.nio.conn.poolignhttpclientconnectionmanager;
导入org.apache.http.impl.nio.reactor.defaultConnectionreactor;
导入org.apache.http.impl.nio.reactor.IOReactorConfig;
导入org.apache.http.nio.conn.NoopIOSessionStrategy;
导入org.apache.http.nio.conn.SchemeIOSessionStrategy;
导入org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
导入javax.net.ssl.SSLContext;
导入javax.net.ssl.SSLException;
导入javax.net.ssl.SSLSession;
导入javax.net.ssl.SSLSocket;
导入java.io.IOException;
导入java.security.cert.CertificateException;
导入java.security.cert.x509证书;
公开课考试
{
私有静态最终动态属性MAX\u TOTAL\u CONNECTIONS=DynamicPropertyFactory.getInstance().getIntProperty(“X.TOTAL.CONNECTIONS”,40);
私有静态最终DynamicProperty路由_CONNECTIONS=DynamicPropertyFactory.getInstance().getIntProperty(“X.total.CONNECTIONS”,40);
私有静态最终动态属性CONNECT\u TIMEOUT=DynamicPropertyFactory.getInstance().getIntProperty(“X.CONNECT.TIMEOUT”,60000);
私有静态最终DynamicProperty SOCKET_TIMEOUT=DynamicPropertyFactory.getInstance().getIntProperty(“X.SOCKET.TIMEOUT”,-1);
私有静态最终DynamicProperty连接\u请求\u超时=DynamicPropertyFactory.getInstance().getIntProperty(“X.connectionrequest.TIMEOUT”,60000);
私有静态final DynamicBooleanProperty STALE_CONNECTION_CHECK=DynamicPropertyFactory.getInstance().getBooleanProperty(“X.checkconnection”,true);
公共静态void main(字符串[]args)引发异常
{
SSLContext SSLContext=SSLContexts.custom()
.useTLS()
.loadTrustMaterial(空,新信任策略()
{
@凌驾
公共布尔isTrusted(X509Certificate[]链,字符串authType)引发CertificateException
{
返回true;
}
})
.build();
SSLIOSessionStrategy sslSessionStrategy=新SSLIOSessionStrategy(sslcontext,new AllowAll());
Registry sessionStrategyRegistry=RegistryBuilder.create()
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
# enable/disable updates of the keystore /etc/ssl/certs/java/cacerts
cacerts_updates=yes
sudo rm /usr/share/ca-certificates/test/test.loc.crt
sudo rm /etc/ssl/certs/java/cacerts
sudo update-ca-certificates --fresh --verbose
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
> sudo ./java-cert-importer.sh example.com
> sudo ./java-cert-importer.sh example.com --delete
   <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.3.6</version>
    </dependency>
jdbc:postgresql://myserver.com:5432/mydatabasename?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory
keytool -import -trustcacerts -alias myselfsignedcert -file /Users/me/Desktop/selfsignedcert.crt -keystore ./privateKeystore.jks
keytool -importkeystore -srckeystore <java-home>/lib/security/cacerts -destkeystore ./privateKeystore.jks
org.gradle.jvmargs=-Djavax.net.debug=SSL -Djavax.net.ssl.trustStore="/Users/me/IntelliJ/myproject/privateKeystore.jks"  -Djavax.net.ssl.trustStorePassword=changeit
javax.net.ssl.SSLHandshakeException: 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.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
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(PKIXValidator.java:387) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) at sun.security.validator.Validator.validate(Validator.java:260) at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026) at sun.security.ssl.Handshaker.process_record(Handshaker.java:961) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747) at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123) at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:138) at SSLPoke.main(SSLPoke.java:31) Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382) ... 15 more
keytool -import -alias <anyname> -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file <cert path>
C:\tools>"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
Successfully connected    
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
C:\java\JDK1.8.0_66-X64\bin>keytool -printcert -file C:\Users\lova\openapi.cer -keystore openapistore
public static void main(String[] args) {
  System.setProperty("javax.net.ssl.trustStore", "trust-store.jks");
  System.setProperty("javax.net.ssl.trustStorePassword", "TrustStore");
  ...
}
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"));
  ...
}
keytool -import -alias ca -keystore trust-store.jks -storepass TrustStore -trustcacerts -file ca.crt
@Service
public class SomeService {

    private final RestTemplate restTemplate;

    private final ObjectMapper objectMapper;    

    private static HttpComponentsClientHttpRequestFactory createRequestFactory() {
        try {
            SSLContextBuilder sslContext = new SSLContextBuilder();
            sslContext.loadTrustMaterial(null, new TrustAllStrategy());
            CloseableHttpClient client = HttpClients.custom().setSSLContext(sslContext.build()).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
            HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
            requestFactory.setHttpClient(client);
            return requestFactory;
        } catch (KeyManagementException | KeyStoreException | NoSuchAlgorithmException var3) {
            throw new IllegalStateException("Couldn't create HTTP Request factory ignore SSL cert validity: ", var3);
        }
    }

    @Autowired
    public SomeService(RestTemplate restTemplate, ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
        this.dimetorURL = dimetorURL;
        restTemplate.setRequestFactory(createRequestFactory());
    }


    public ResponseEntity<ResponseObject> sendRequest(RequestObject requestObject) {
        //...
        return restTemplate.exchange(url, HttpMethod.GET, ResponseObject.class);
        //...
    }
}
mvn -ea -Dtestng.dtd.http=true  -Djavax.net.ssl.trustStore=C:\Users\me\.keystore -Djavax.net.ssl.trustStorePassword=X -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true -Dmaven.wagon.http.ssl.ignore.validity.dates=true -Dcucumber.features=src/test/resources -Dcucumber.glue=com.myapp -Dcucumber.filter.tags="@MY_TEST"