JAVA桌面应用程序不能访问HTTPS的解决方法

用java访问https时,有可能会出现不能访问的错误:

  • 若是用4.1版本的HttpClient包,则会出现javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated的异常;
  • 若是用4.5.8版本的HttpClient包,则会出现PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target的异常。

经测试有两种解决方法,分别是:

  1. 用keytool命令将SSL证书导入到密钥库;
  2. 直接绕过SSL认证;

如果做java GUI,第一种方法过于麻烦,这次详细记录网上的第二种方法:

public class SslUtil{
    public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {  
      SSLContext sc = SSLContext.getInstance("SSLv3");  

      // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法  
      X509TrustManager trustManager = new X509TrustManager() {  
          @Override  
          public void checkClientTrusted(  
                  java.security.cert.X509Certificate[] paramArrayOfX509Certificate,  
                  String paramString) throws CertificateException {  
          }  

          @Override  
          public void checkServerTrusted(  
                  java.security.cert.X509Certificate[] paramArrayOfX509Certificate,  
                  String paramString) throws CertificateException {  
          }  

          @Override  
          public java.security.cert.X509Certificate[] getAcceptedIssuers() {  
              return null;  
          }  
      };  

      sc.init(null, new TrustManager[] { trustManager }, null);  
      return sc;  
    }

    public static CloseableHttpClient  getHttpClient(){

      //采用绕过验证的方式处理https请求  
      SSLContext sslcontext = createIgnoreVerifySSL();  

      //设置协议http和https对应的处理socket链接工厂的对象  
      Registry socketFactoryRegistry = RegistryBuilder.create()  
          .register("http", PlainConnectionSocketFactory.INSTANCE)  
          .register("https", new SSLConnectionSocketFactory(sslcontext))  
          .build();  
      PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);  


      //创建自定义的httpclient对象  
      CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build();  
      //CloseableHttpClient client = HttpClients.createDefault(); 
      return client; 
    }
}

用SslUtil类中静态方法getHttpClient()返回的CloseableHttpClient处理POST,GET请求即可。

网上还有一种处理方法,代码如下:

import java.security.cert.CertificateException;  
import java.security.cert.X509Certificate;  
import javax.net.ssl.HostnameVerifier;  
import javax.net.ssl.HttpsURLConnection;  
import javax.net.ssl.SSLContext;  
import javax.net.ssl.SSLSession;  
import javax.net.ssl.TrustManager;  
import javax.net.ssl.X509TrustManager;  
public class SslUtils {  
    private static void trustAllHttpsCertificates() throws Exception {  
        TrustManager[] trustAllCerts = new TrustManager[1];  
        TrustManager tm = new miTM();  
        trustAllCerts[0] = tm;  
        SSLContext sc = SSLContext.getInstance("SSL");  
        sc.init(null, trustAllCerts, null);  
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());  
    }  
    static class miTM implements TrustManager,X509TrustManager {  
        public X509Certificate[] getAcceptedIssuers() {  
            return null;  
        }  
        public boolean isServerTrusted(X509Certificate[] certs) {  
            return true;  
        }  
        public boolean isClientTrusted(X509Certificate[] certs) {  
            return true;  
        }  
        public void checkServerTrusted(X509Certificate[] certs, String authType)  
                throws CertificateException {  
            return;  
        }  
        public void checkClientTrusted(X509Certificate[] certs, String authType)  
                throws CertificateException {  
            return;  
        }  
    }  
    /** 
     * 忽略HTTPS请求的SSL证书,必须在openConnection之前调用 
     * @throws Exception 
     */  
    public static void ignoreSsl() throws Exception{  
        HostnameVerifier hv = new HostnameVerifier() {  
            public boolean verify(String urlHostName, SSLSession session) {  
                System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());  
                return true;  
            }  
        };  
        trustAllHttpsCertificates();  
        HttpsURLConnection.setDefaultHostnameVerifier(hv);  
    }  
}  

不过这种方法我这里没有成功,可能是因为自己用了HttpClient框架,而不是URL标准类的缘故。

你可能感兴趣的:(JAVA桌面应用程序不能访问HTTPS的解决方法)