Java: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

前端 未结 23 1058
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-22 04:44

I have a class that will download a file from a https server. When I run it, it returns a lot of errors. It seems that I have a problem with my certificate

相关标签:
23条回答
  • 2020-11-22 05:03

    Simple Steps that I followed.

    problem: I was trying to connect to an endpoint(https://%s.blob.core.windows.net) using a simple java class(main method).

    So I was getting this certification issue as mentioned above, in the question.

    Solution:

    1. Get the certificate using a browser(chrome). To do this paste your endpoint URL in the browser and enter. Now you will see a lock icon, click on that -->certificate--> details --> copy to files--> download it.

    2. open the cmd(i am using windows) as admin and then navigate to the directory where you have downloaded the .cer file.

    3.(Optional)If you are using multiple JDK in the same machine then change your JDK version the same as you are using in your application.

    1. Now use the below command

    keytool -import -alias mycertificate -keystore "C:\Program Files\Java\jdk-11.0.5\lib\security\cacerts" -file myurlcrt.cer

    1. Give the default password: changeit

    2. Trust this certificate: yes

    And you are done.

    Thanks!

    0 讨论(0)
  • 2020-11-22 05:04

    For Windows only, follow these steps:

    1. In Chrome go to settings.
    2. In Settings click show advance settings.
    3. Under HTTPS/SSL Click on Manage Certificates.
    4. Export Your Certificate.
    5. In Windows searchs (Pressing windows key on keyboard) type java.
    6. Select (Configure Java) Option Which will open Java Control Panel
    7. Select Security tab in Java Control Panel
    8. Select Manage Certificates
    9. Click Import
    10. Under (User) tab selected and certificate type as (Trusted Certificates)
    11. Click import button and browse to downloaded certificate and import it.
    0 讨论(0)
  • 2020-11-22 05:04

    I was able to get it working with code only, i.e. no need to use 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;
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 05:06

    The source of this error on my Apache 2.4 instance (using a Comodo wildcard certificate) was an incomplete path to the SHA-1 signed root certificate. There were multiple chains in the issued certificate, and the chain leading to a SHA-1 root certificate was missing an intermediate certificate. Modern browsers know how to handle this, but Java 7 doesn't handle it by default (although there are some convoluted ways to accomplish this in code). The result is error messages that look identical to the case of self-signed certificates:

    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
    

    In this case, the "unable to find valid certification path to requested target" message is being produced due to the missing intermediate certificate. You can check which certificate is missing using SSL Labs test against the server. Once you find the appropriate certificate, download it and (if the server is under your control) add it to the certificate bundle. Alternatively, you can import the missing certificate locally. Accommodating this issue on the server is a more general solution to the problem.

    0 讨论(0)
  • 2020-11-22 05:09

    There is a lot of way to solve this...

    One way is set the TrustStore certificates in a keystore file and put it in the path of the application, and set these system properties in the main method:

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

    Other way is place the keystore as resource file inside the project jar file and load it:

    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"));
      ...
    }
    

    In windows you can try this solution too: https://stackoverflow.com/a/59056537/980442


    I created the keystore file from a Certificate authority CA .crt file in this way:

    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

    0 讨论(0)
  • 2020-11-22 05:09

    You have two options, import the self-signed cert into java's keystore for each jvm the software will run on or try the non-validating ssl factory:

    jdbc:postgresql://myserver.com:5432/mydatabasename?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory
    
    0 讨论(0)
提交回复
热议问题