PKIX路径构建失败:在生产服务器中不起作用。它不信任证书

时间:2017-02-08 09:17:23

标签: java api ssl https ssl-certificate

当我在生产环境中部署它时,我的J2EE应用程序抛出异常。我已经尝试过keytool生成的自签名证书,但它没有任何意义

JDK :( Oracle JDK)java版“1.7.0_80” Tomcat:7.0.55

javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到所请求目标的有效证书路径

此应用程序与需要通过HTTPS进行通信的API进行对话。以下是代码段:

public  String reqSender() throws Exception 
{

String inputLine="xxxxx";
String refreshToken="addddddd";
String httpsURL = "https://mifc.xxx.lk/xxx/token?grant_type=refresh_token&refresh_token="
                        + refreshToken + "&scope=PRODUCTION";



URL myurl = new URL(httpsURL);

HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
con.setRequestMethod("POST");

con.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
con.setRequestProperty("Authorization","Basic YxsdsdsfdfsfsdsdsdSncxU0dlQXJPY3F1Q1JndXc3bU1h");


InputStream ins = con.getInputStream();


InputStreamReader isr = new InputStreamReader(ins);


    try (BufferedReader in = new BufferedReader(isr)) {

        while ((inputLine = in.readLine()) != null)
        {
            System.out.println(inputLine);
        }   }
    return inputLine;}

1 个答案:

答案 0 :(得分:1)

问题原因:客户端无法信任我们尝试访问的服务器端证书。因此我写了使用HttpsURLConnection扩展HttpURLConnection和X509TrustManager进行身份验证。还使用了单独的类“SSLCert”来信任证书。这样客户就可以信任证书并按预期进行通信。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import static java.lang.Math.log;
import static java.lang.System.out;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.json.JSONObject;

import java.security.GeneralSecurityException;
import java.security.SecureRandom;
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 String reqSender()() throws Exception {
        String acessToken = null;
        String rfshToken = null;
        double expiresIn = 0.0D;
        int x = 0;
        SSLCert.trustAllHostnames();
        SSLCert.trustAllHttpsCertificates();
        //DbCon con = new DbCon();

        try {
            String refreshToken = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
            System.out.println(refreshToken);
            System.out.println("");
            System.out.println("Calling web service...");

            URL url = new URL(
                    "https://mifxx.xxxxx.lk/apicall/token?grant_type=refresh_token&refresh_token="
                    + refreshToken + "&scope=PRODUCTION");
            System.out.println("web service called" + url.toString());
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            conn.setRequestProperty(
                    "Authorization",
                    "Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1JndXc3bU1h");
    enter code here
            /////start
            HttpsURLConnection conHttps = (HttpsURLConnection) conn;
            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) {
                }
            }};

            HostnameVerifier allHostsValid = new HostnameVerifier() {
                @Override
                public boolean verify(String arg0, SSLSession arg1) {
                    return true;
                }
            };

            // Install the all-trusting trust manager
            try {
                SSLContext sc = SSLContext.getInstance("SSL");
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
                HttpsURLConnection.setDefaultSSLSocketFactory(sc
                        .getSocketFactory());
                HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
                conn = conHttps;
            } catch (Exception e) {
            }

            /////End
            x = conn.getResponseCode();
            System.out.println(conn.getResponseCode() + "CODE");
            if (conn.getResponseCode() != 200) {
                throw new RuntimeException("Failed : HTTP error code : "
                        + conn.getResponseCode());
            }

            BufferedReader br = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));

            System.out.println("Output from Server ....");
            String output = null;
            while ((output = br.readLine()) != null) {
                System.out.println(output);

                JSONObject obj = new JSONObject(output);
                String defult = obj.getString("scope");
                String tokenType = obj.getString("token_type");
                expiresIn = obj.getDouble("expires_in");
                rfshToken = obj.getString("refresh_token");
                acessToken = obj.getString("access_token");

                System.out.println("");
                System.out.println("-------------------------");
                System.out.println("Access Token :" + acessToken);
                System.out.println("Refresh Token :" + rfshToken);
                System.out.println("Token Type :" + tokenType);
                System.out.println("Scope :" + defult);
                System.out.println("Expiration time: " + expiresIn);
                System.out.println("-------------------------");
                System.out.println("");
            }

            conn.disconnect();
        } catch (MalformedURLException e) {
            //log.error(e);
            e.printStackTrace();
        } catch (IOException e) {
            //log.error(e);
            e.printStackTrace();
        }
        return rfshToken;
    }

以下课程是SSLCert

 SSLCert class

import java.security.GeneralSecurityException;
 import java.security.SecureRandom;
 import java.security.cert.X509Certificate;
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;

 /**
  * This class provide various static methods that relax X509 certificate and 
  * hostname verification while using the SSL over the HTTP protocol.
  *
  * 
  */
 public final class SSLCert {

   /**
    * Hostname verifier for the Sun's deprecated API.
    *
    * @deprecated see {@link #_hostnameVerifier}.
    */
   private static com.sun.net.ssl.HostnameVerifier __hostnameVerifier;
   /**
    * Thrust managers for the Sun's deprecated API.
    *
    * @deprecated see {@link #_trustManagers}.
    */
   private static com.sun.net.ssl.TrustManager[] __trustManagers;
   /**
    * Hostname verifier.
    */
   private static HostnameVerifier _hostnameVerifier;
   /**
    * Thrust managers.
    */
   private static TrustManager[] _trustManagers;


   /**
    * Set the default Hostname Verifier to an instance of a fake class that 
    * trust all hostnames. This method uses the old deprecated API from the 
    * com.sun.ssl package.
    *
    * @deprecated see {@link #_trustAllHostnames()}.
    */
   private static void __trustAllHostnames() {
       // Create a trust manager that does not validate certificate chains
       if(__hostnameVerifier == null) {
           __hostnameVerifier = new _FakeHostnameVerifier();
       } // if
       // Install the all-trusting host name verifier
       com.sun.net.ssl.HttpsURLConnection.
           setDefaultHostnameVerifier(__hostnameVerifier);
   } // __trustAllHttpsCertificates

   /**
    * Set the default X509 Trust Manager to an instance of a fake class that 
    * trust all certificates, even the self-signed ones. This method uses the 
    * old deprecated API from the com.sun.ssl package.
    *
    * @deprecated see {@link #_trustAllHttpsCertificates()}.
    */
   private static void __trustAllHttpsCertificates() {
       com.sun.net.ssl.SSLContext context;

       // Create a trust manager that does not validate certificate chains
       if(__trustManagers == null) {
           __trustManagers = new com.sun.net.ssl.TrustManager[] 
               {new _FakeX509TrustManager()};
       } // if
       // Install the all-trusting trust manager
       try {
           context = com.sun.net.ssl.SSLContext.getInstance("SSL");
           context.init(null, __trustManagers, new SecureRandom());
       } catch(GeneralSecurityException gse) {
           throw new IllegalStateException(gse.getMessage());
       } // catch
       com.sun.net.ssl.HttpsURLConnection.
           setDefaultSSLSocketFactory(context.getSocketFactory());
   } // __trustAllHttpsCertificates

   /**
    * Return true if the protocol handler property java.
    * protocol.handler.pkgs is set to the Sun's com.sun.net.ssl.
    * internal.www.protocol deprecated one, false 
    * otherwise.
    *
    * @return                true if the protocol handler 
    * property is set to the Sun's deprecated one, false 
    * otherwise.
    */
   private static boolean isDeprecatedSSLProtocol() {
       return("com.sun.net.ssl.internal.www.protocol".equals(System.
           getProperty("java.protocol.handler.pkgs")));
   } // isDeprecatedSSLProtocol

   /**
    * Set the default Hostname Verifier to an instance of a fake class that 
    * trust all hostnames.
    */
   private static void _trustAllHostnames() {
       // Create a trust manager that does not validate certificate chains
       if(_hostnameVerifier == null) {
           _hostnameVerifier = new FakeHostnameVerifier();
       } // if
         // Install the all-trusting host name verifier:
       HttpsURLConnection.setDefaultHostnameVerifier(_hostnameVerifier);
   } // _trustAllHttpsCertificates

   /**
    * Set the default X509 Trust Manager to an instance of a fake class that 
    * trust all certificates, even the self-signed ones.
    */
   private static void _trustAllHttpsCertificates() {
       SSLContext context;

       // Create a trust manager that does not validate certificate chains
       if(_trustManagers == null) {
           _trustManagers = new TrustManager[] {new FakeX509TrustManager()};
       } // if
       // Install the all-trusting trust manager:
       try {
       context = SSLContext.getInstance("SSL");
       context.init(null, _trustManagers, new SecureRandom());
       } catch(GeneralSecurityException gse) {
           throw new IllegalStateException(gse.getMessage());
       } // catch
       HttpsURLConnection.setDefaultSSLSocketFactory(context.
           getSocketFactory());
   } // _trustAllHttpsCertificates

   /**
    * Set the default Hostname Verifier to an instance of a fake class that 
    * trust all hostnames.
    */
   public static void trustAllHostnames() {
       // Is the deprecated protocol setted?
       if(isDeprecatedSSLProtocol()) {
           __trustAllHostnames();
       } else {
           _trustAllHostnames();
       } // else
   } // trustAllHostnames

   /**
    * Set the default X509 Trust Manager to an instance of a fake class that 
    * trust all certificates, even the self-signed ones.
    */
   public static void trustAllHttpsCertificates() {
       // Is the deprecated protocol setted?
       if(isDeprecatedSSLProtocol()) {
           __trustAllHttpsCertificates();
       } else {
           _trustAllHttpsCertificates();
       } // else
   } // trustAllHttpsCertificates

   /**
    * This class implements a fake hostname verificator, trusting any host 
    * name. This class uses the old deprecated API from the com.sun.
    * ssl package.
    *
    * 
    *
    * @deprecated see {@link SSLCert.FakeHostnameVerifier}.
    */
   public static class _FakeHostnameVerifier 
       implements com.sun.net.ssl.HostnameVerifier {

       /**
        * Always return true, indicating that the host name is an 
        * acceptable match with the server's authentication scheme.
        *
        * @param hostname        the host name.
        * @param session         the SSL session used on the connection to 
        * host.
        * @return                the true boolean value 
        * indicating the host name is trusted.
        */
       public boolean verify(String hostname, String session) {
           return(true);
       } // verify
   } // _FakeHostnameVerifier


   /**
    * This class allow any X509 certificates to be used to authenticate the 
    * remote side of a secure socket, including self-signed certificates. This 
    * class uses the old deprecated API from the com.sun.ssl 
    * package.
    *
    * 
    *
    * @deprecated see {@link SSLCert.FakeX509TrustManager}.
    */
   public static class _FakeX509TrustManager 
       implements com.sun.net.ssl.X509TrustManager {

       /**
        * Empty array of certificate authority certificates.
        */
       private static final X509Certificate[] _AcceptedIssuers = 
           new X509Certificate[] {};


       /**
        * Always return true, trusting for client SSL 
        * chain peer certificate chain.
        *
        * @param chain           the peer certificate chain.
        * @return                the true boolean value 
        * indicating the chain is trusted.
        */
       public boolean isClientTrusted(X509Certificate[] chain) {
           return(true);
       } // checkClientTrusted

       /**
        * Always return true, trusting for server SSL 
        * chain peer certificate chain.
        *
        * @param chain           the peer certificate chain.
        * @return                the true boolean value 
        * indicating the chain is trusted.
        */
       public boolean isServerTrusted(X509Certificate[] chain) {
           return(true);
       } // checkServerTrusted

       /**
        * Return an empty array of certificate authority certificates which 
        * are trusted for authenticating peers.
        *
        * @return                a empty array of issuer certificates.
        */
       public X509Certificate[] getAcceptedIssuers() {
           return(_AcceptedIssuers);
       } // getAcceptedIssuers
   } // _FakeX509TrustManager


   /**
    * This class implements a fake hostname verificator, trusting any host 
    * name.
    *
    * 
    */
   public static class FakeHostnameVerifier implements HostnameVerifier {

       /**
        * Always return true, indicating that the host name is 
        * an acceptable match with the server's authentication scheme.
        *
        * @param hostname        the host name.
        * @param session         the SSL session used on the connection to 
        * host.
        * @return                the true boolean value 
        * indicating the host name is trusted.
        */
       public boolean verify(String hostname, 
           javax.net.ssl.SSLSession session) {
           return(true);
       } // verify
   } // FakeHostnameVerifier


   /**
    * This class allow any X509 certificates to be used to authenticate the 
    * remote side of a secure socket, including self-signed certificates.
    *
    * 
    */
   public static class FakeX509TrustManager implements X509TrustManager {

       /**
        * Empty array of certificate authority certificates.
        */
       private static final X509Certificate[] _AcceptedIssuers = 
           new X509Certificate[] {};


       /**
        * Always trust for client SSL chain peer certificate 
        * chain with any authType authentication types.
        *
        * @param chain           the peer certificate chain.
        * @param authType        the authentication type based on the client 
        * certificate.
        */
       public void checkClientTrusted(X509Certificate[] chain, 
           String authType) {
       } // checkClientTrusted

       /**
        * Always trust for server SSL chain peer certificate 
        * chain with any authType exchange algorithm types.
        *
        * @param chain           the peer certificate chain.
        * @param authType        the key exchange algorithm used.
        */
       public void checkServerTrusted(X509Certificate[] chain, 
           String authType) {
       } // checkServerTrusted

       /**
        * Return an empty array of certificate authority certificates which 
        * are trusted for authenticating peers.
        *
        * @return                a empty array of issuer certificates.
        */
       public X509Certificate[] getAcceptedIssuers() {
           return(_AcceptedIssuers);
       } // getAcceptedIssuers
   } // FakeX509TrustManager
 } // SSLCert