Java SSL HTTPS进行双重认证开发实践

1、我们先将.cer 和.jks文件导出然后发给服务端进行证书认证才好进行接下来的开发
  1.1、至于如何导出:
  命令1.keytool -genkeypair -dname "cn=clientAuth_PhevBattery, ou=IS, o=SGM, c=CN" -alias clientAuthCert -keypass Pass1234 -keystore d:\clientAuth_PhevBattery.jks -storepass Pass1234 -validity 3600  -keyalg RSA -keysize 2048 -sigalg SHA256WithRSA
  命令2:keytool -export -file d:\clientAuth_PhevBattery.cer -keystore d:\clientAuth_PhevBattery.jks -storepass Pass1234 -alias clientAuthCert
   PS:.cer是我们的证书保存了公钥,.jks保存的公钥和秘钥的算法  个人理解,如果错了希望大家可以提供改正,谢谢
2、开发过程中遇到两个问题
   1.1、没搞明白JDK的security/cacerts库的是什么意思
        经查询资料显示cacerts是一个秘钥库,我们在执行SSL认证的时候会使用到
   1.2、客户没有将我们导出的.cer证书成功的加入到秘钥库进行受信任,所以在测试的过程中程序报错
        javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found

      


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

public class ClientCertAuthSample {

   // JKS文件
   public static String KEY_STORE_FILE = "/Users/lkj/Desktop/clientAuth_PhevBattery.jks";
   // JKS文件密码
   public static String KEY_STORE_PASS = "Pass1234";

   // jre安全库文件
   // 一般默认位置 jdk1.8.0_161.jdk/jre/lib/security/cacerts

   public static String TRUST_STORE_FILE = "/Users/lkj/Desktop/cacerts";
   // 密匙库默认密码
   public static String TRUST_STORE_PASS = "changeit";

   final static String param = "{\"System_Type\": \"TDS3P\",\"data\": [{\"ModuleId\": \"268435912\",\"ICCID\": \"89860617020017346325\",\"PhoneNumber\": \"\",\"IMSI\": \"\",\"GM_Defined_Part_Number\": \"26245447\",\"GM_Defined_VPPS\": \"0000000075204X\",\"DUNSID_of_Production_Site\": \"545245003\",\"GM_Defined_Tracebility_Code\": \"1117136A00000069\",\"ModuleType\": \"\",\"Manufacturer\": \"\",\"GM_Program \": \"\"},{\"ModuleId\": \"268435913\",\"ICCID\": \"89860617020017346317\",\"PhoneNumber\": \"\",\"IMSI\": \"\",\"GM_Defined_Part_Number\": \"26245447\",\"GM_Defined_VPPS\": \"0000000075204X\",\"DUNSID_of_Production_Site\": \"545245003\",\"GM_Defined_Tracebility_Code\": \"1117136A00000078\",\"ModuleType\": \"\",\"Manufacturer\": \"\",\"GM_Program \": \"\"}] }";

   private static SSLContext sslContext;

   /**
    * 向指定URL发送GET方法的请求
    *
    * @param url
    *            发送请求的URL
    * @param param
    *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
    * @return URL 所代表远程资源的响应结果
    *
    */
   public static String sendGet(String url, String param) {
      String result = "";
      BufferedReader in = null;
      try {
         String urlNameString = url;
         if (param != null) {
            urlNameString = url + "?" + param;
         }
         URL realUrl = new URL(urlNameString);
         // 打开和URL之间的连接
         HttpsURLConnection connection = (HttpsURLConnection) realUrl.openConnection();
         HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
               return true;
            }
         });
         // 打开和URL之间的连接
         connection.setSSLSocketFactory(getSSLContext().getSocketFactory());
         // 设置通用的请求属性
         connection.setRequestProperty("accept", "*/*");
         connection.setRequestProperty("connection", "Keep-Alive");
         // connection.setRequestProperty("content-type",
         // "application/json");
         connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
         // 建立实际的连接
         connection.connect();
         // 获取所有响应头字段
         Map> map = connection.getHeaderFields();
         // 遍历所有的响应头字段
         for (String key : map.keySet()) {
            System.out.println(key + "--->" + map.get(key));
         }
         // 定义 BufferedReader输入流来读取URL的响应

         if (connection.getResponseCode() == 200) {
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
         } else {
            in = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
         }
         String line;
         while ((line = in.readLine()) != null) {
            result += line;
         }

      } catch (Exception e) {
         System.out.println("发送GET请求出现异常!" + e);
         e.printStackTrace();
      }
      // 使用finally块来关闭输入流
      finally {
         try {
            if (in != null) {
               in.close();
            }
         } catch (Exception e2) {
            e2.printStackTrace();
         }
      }
      return result;
   }

   /**
    * 向指定 URL 发送POST方法的请求
    *
    * @param url
    *            发送请求的 URL
    * @param param
    *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
    * @return 所代表远程资源的响应结果
    */
   public static String sendPost(String url, String param) {
      PrintWriter out = null;
      BufferedReader in = null;
      String result = "";
      try {
         URL realUrl = new URL(url);
         System.out.println(
               "host=" + realUrl.getHost() + "\n;port=" + realUrl.getPort() + "\n;path=" + realUrl.getPath());
         // 打开和URL之间的连接
         HttpsURLConnection conn = (HttpsURLConnection) realUrl.openConnection();
         // 打开和URL之间的连接
         conn.setSSLSocketFactory(getSSLContext().getSocketFactory());
         // 设置通用的请求属性
         // 发送POST请求必须设置如下两行
         conn.setDoOutput(true);
         conn.setDoInput(true);
         conn.setRequestProperty("accept", "application/json");
         conn.setRequestMethod("POST");
         conn.setRequestProperty("Content-Type", "application/json");
         conn.setRequestProperty("connection", "Keep-Alive");
         conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
         conn.connect();
         // 获取URLConnection对象对应的输出流
         OutputStream os = conn.getOutputStream();
         out = new PrintWriter(os);
         // 发送请求参数
         out.print(param);
         // flush输出流的缓冲
         out.flush();
         // 定义BufferedReader输入流来读取URL的响应
         System.out.println(conn.getResponseCode());
         if (conn.getResponseCode() == 200) {
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
         } else {
            in = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
         }
         String line = "";
         while ((line = in.readLine()) != null) {
            result += line;
         }
      } catch (Exception e) {
         System.out.println("发送 POST 请求出现异常!" + e);
         e.printStackTrace();
      }
      // 使用finally块来关闭输出流、输入流
      finally {
         try {
            if (out != null) {
               out.close();
            }
            if (in != null) {
               in.close();
            }
         } catch (IOException ex) {
            ex.printStackTrace();
         }
      }
      return result;
   }

   public static SSLContext getSSLContext() {
      long time1 = System.currentTimeMillis();
      if (sslContext == null) {
         try {
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(getkeyStore(), KEY_STORE_PASS.toCharArray());
            KeyManager[] keyManagers = kmf.getKeyManagers();

            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
            trustManagerFactory.init(getTrustStore());
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

            sslContext = SSLContext.getInstance("TLSv1");
            sslContext.init(keyManagers, trustManagers, new SecureRandom());
            System.out.println(sslContext.getProtocol() + "NNNNN:" + sslContext.getProvider().toString());
         } catch (FileNotFoundException e) {
            e.printStackTrace();
         } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
         } catch (IOException e) {
            e.printStackTrace();
         } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
         } catch (KeyStoreException e) {
            e.printStackTrace();
         } catch (KeyManagementException e) {
            e.printStackTrace();
         }
      }
      long time2 = System.currentTimeMillis();
      System.out.println("SSLContext 初始化时间:" + (time2 - time1));
      return sslContext;
   }

   public static KeyStore getkeyStore() {
      KeyStore keySotre = null;
      try {
         // keySotre = KeyStore.getInstance("PKCS12");
         keySotre = KeyStore.getInstance("JKS");
         FileInputStream fis = new FileInputStream(new File(KEY_STORE_FILE));
         keySotre.load(fis, KEY_STORE_PASS.toCharArray());
         fis.close();
      } catch (KeyStoreException e) {
         e.printStackTrace();
      } catch (FileNotFoundException e) {
         e.printStackTrace();
      } catch (NoSuchAlgorithmException e) {
         e.printStackTrace();
      } catch (CertificateException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
      return keySotre;
   }

   public static KeyStore getTrustStore() throws IOException {
      KeyStore trustKeyStore = null;
      FileInputStream fis = null;
      try {
         trustKeyStore = KeyStore.getInstance("JKS");
         fis = new FileInputStream(new File(TRUST_STORE_FILE));
         trustKeyStore.load(fis, TRUST_STORE_PASS.toCharArray());
      } catch (FileNotFoundException e) {
         e.printStackTrace();
      } catch (KeyStoreException e) {
         e.printStackTrace();
      } catch (NoSuchAlgorithmException e) {
         e.printStackTrace();
      } catch (CertificateException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      } finally {
         fis.close();
      }
      return trustKeyStore;
   }

   public static void main(String[] args) throws Exception {
      // add();
      System.setProperty("javax.net.debug", "ssl,handshake,record");
      Long time1 = System.currentTimeMillis();
      int k = 0;
      String result = sendPost("www.baidu.com", param);//PS:www.baidu.com是URL请求路径并非是测试路径,请更换自己的
      System.out.println("result+" + result);
      Long time2 = System.currentTimeMillis();
      System.out.println("平均耗费时间:" + (time2 - time1) / ++k);
   }

}

你可能感兴趣的:(Java)