向https地址发送请求失败报错

向https地址发送请求失败报错

码农世界 2024-06-13 后端 93 次浏览 0个评论

错误1:

10:13:47.520 [main] DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - Starting handshake
10:13:47.523 [main] DEBUG org.apache.http.impl.conn.DefaultManagedHttpClientConnection - http-outgoing-0: Shutdown connection
10:13:47.523 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - Connection discarded
10:13:47.523 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection released: [id: 0][route: {s}->https://223.108.104.37:8180][total available: 0; route allocated: 0 of 2; total allocated: 0 of 20]
10:13:47.524 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection manager is shutting down
10:13:47.524 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection manager shut down
Exception in thread "main" javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
	at sun.security.ssl.HandshakeContext.(HandshakeContext.java:171)
	at sun.security.ssl.ClientHandshakeContext.(ClientHandshakeContext.java:106)
	at sun.security.ssl.TransportContext.kickstart(TransportContext.java:245)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:410)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:389)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384)
	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
  • SSLHandshakeException 异常:我这边是使用的协议TLSv1版本太低,换一个就行
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                        sslcontext,
                        new String[]{"TLSv1.2"},  // 使用 TLSv1.2 协议
                        null,
                        NoopHostnameVerifier.INSTANCE);

    错误2:

    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.Alert.createSSLException(Alert.java:131)
    	at sun.security.ssl.TransportContext.fatal(TransportContext.java:377)
    	at sun.security.ssl.TransportContext.fatal(TransportContext.java:320)
    	at sun.security.ssl.TransportContext.fatal(TransportContext.java:315)
    	at sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:652)
    	at sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:471)
    	at sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:367)
    	at sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:376)
    	at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:479)
    	at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:457)
    	at sun.security.ssl.TransportContext.dispatch(TransportContext.java:200)
    	at sun.security.ssl.SSLTransport.decode(SSLTransport.java:155)
    	at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1320)
    	at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1233)
    	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:417)
    	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:389)
    	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436)
    	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384)
    	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
    	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
    	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
    	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
    	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
    	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
    	at com.waterapidemo.util.HttpPostUtil.sslRequest(HttpPostUtil.java:108)
    	at com.waterapidemo.util.HttpPostUtil.main(HttpPostUtil.java:74)
    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(PKIXValidator.java:439)
    	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
    	at sun.security.validator.Validator.validate(Validator.java:271)
    	at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:312)
    	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:221)
    	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:128)
    	at sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:636)
    	... 25 more
    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:148)
    • ​JVM默认信任证书不包含该目标网站的SSL证书,导致无法建立有效的信任链接。

      keytool -importcert -alias xxx.xxx.xxx.xxx -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -file xxxxx.cert 

       解决办法:

      1.获取服务器的证书

      package com.waterapidemo.util;
      import java.io.FileOutputStream;
      import java.io.InputStream;
      import java.net.Socket;
      import java.security.cert.Certificate;
      import java.security.cert.CertificateFactory;
      import javax.net.ssl.SSLContext;
      import javax.net.ssl.SSLSocket;
      import javax.net.ssl.SSLSocketFactory;
      import javax.net.ssl.TrustManager;
      import javax.net.ssl.X509TrustManager;
      public class FetchServerCert {
          private static final String SERVER_HOST = "xxxxxxxxx";
          private static final int SERVER_PORT = xxxx;
          private static final String CERT_FILE = "X:\\xxx\\server-cert.cer";
          public static void main(String[] args) {
              try {
                  // Step 1: Set up a TrustManager that accepts all certificates
                  TrustManager[] trustAllCerts = new TrustManager[]{
                          new X509TrustManager() {
                              public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                                  return null;
                              }
                              public void checkClientTrusted(
                                      java.security.cert.X509Certificate[] certs, String authType) {
                              }
                              public void checkServerTrusted(
                                      java.security.cert.X509Certificate[] certs, String authType) {
                              }
                          }
                  };
                  SSLContext sslContext = SSLContext.getInstance("TLS");
                  sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
                  SSLSocketFactory factory = sslContext.getSocketFactory();
                  // Step 2: Connect to the server and retrieve the server certificate
                  try (SSLSocket socket = (SSLSocket) factory.createSocket(SERVER_HOST, SERVER_PORT)) {
                      socket.startHandshake();
                      Certificate[] serverCerts = socket.getSession().getPeerCertificates();
                      // Step 3: Save the first server certificate to a file
                      try (FileOutputStream fos = new FileOutputStream(CERT_FILE)) {
                          fos.write(serverCerts[0].getEncoded());
                      }
                      System.out.println("Server certificate saved to " + CERT_FILE);
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      }
      
      • 定义一个自定义的 TrustManager,它将接受所有证书

        2.将证书导入JVM信任库

        package com.waterapidemo.util;
        import java.io.*;
        import java.security.KeyStore;
        import java.security.cert.Certificate;
        import java.security.cert.CertificateFactory;
        import java.security.cert.X509Certificate;
        public class ImportServerCert {
            private static final String CERT_FILE = "X:\\xxx\\server-cert.cer";
            private static final String TRUSTSTORE_PATH = "X:\\xxx\\truststore.jks";
            private static final String TRUSTSTORE_PASSWORD = "changeit";
            public static void main(String[] args) {
                try {
                    // Load the server certificate from the file
                    Certificate serverCert = loadCertificate(CERT_FILE);
                    // Create a truststore and add the server certificate to it
                    KeyStore trustStore = createTrustStore(serverCert, TRUSTSTORE_PATH, TRUSTSTORE_PASSWORD);
                    // Save the truststore to a file
                    try (FileOutputStream fos = new FileOutputStream(TRUSTSTORE_PATH)) {
                        trustStore.store(fos, TRUSTSTORE_PASSWORD.toCharArray());
                        System.out.println("Truststore created and saved to " + TRUSTSTORE_PATH);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            private static Certificate loadCertificate(String certFilePath) throws Exception {
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                try (FileInputStream fis = new FileInputStream(certFilePath)) {
                    return cf.generateCertificate(fis);
                }
            }
            private static KeyStore createTrustStore(Certificate cert, String trustStorePath, String trustStorePassword) throws Exception {
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                trustStore.load(null, null); // Initialize the empty truststore
                String alias = "server-cert";
                trustStore.setCertificateEntry(alias, cert);
                return trustStore;
            }
        }
        

        3.请求的时候携带好证书就可以了

            public static String sslRequest(String url, String params, String token) throws Exception {
                String results;
                // Load client certificate
                KeyStore keyStore = KeyStore.getInstance("xxxx");
                try (FileInputStream keyStoreStream = new FileInputStream(PATH)) {
                    keyStore.load(keyStoreStream, PASSWORD.toCharArray());
                }
                // Load truststore containing server certificate
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                try (FileInputStream trustStoreStream = new FileInputStream(TRUSTSTORE_PATH)) {
                    trustStore.load(trustStoreStream, TRUSTSTORE_PASSWORD.toCharArray());
                }
                // Set up SSL context with client certificate and truststore
                SSLContext sslContext = SSLContexts.custom()
                        .loadKeyMaterial(keyStore, PASSWORD.toCharArray())
                        .loadTrustMaterial(trustStore, null)
                        .build();
                // Create SSL connection factory
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
                // Create HTTP client with custom SSL context
                try (CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build()) {
                    // Create HTTP POST request
                    HttpPost httpPost = new HttpPost(url);
                    httpPost.setHeader("FROM", token);
                    httpPost.setEntity(new StringEntity(params, "UTF-8"));
                    // Execute request
                    try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                        HttpEntity entity = response.getEntity();
                        results = EntityUtils.toString(entity, "UTF-8");
                        EntityUtils.consume(entity);
                    }
                }
                return results;
            }

转载请注明来自码农世界,本文标题:《向https地址发送请求失败报错》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,93人围观)参与讨论

还没有评论,来说两句吧...

Top