少年阿賓

          那些青春的歲月

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks

          https一般來說有單項SSL和雙向SSL連接之分。

           

          單項SSL連接,也就是只是客戶端驗證服務器證書。tomcat中clientAuth="false"的時候,HTTPS單向驗證如下:

          import java.io.BufferedReader;
          import java.io.InputStreamReader;
          import java.io.OutputStream;
          import java.net.URL;
          import java.util.Date;
          import javax.net.ssl.HostnameVerifier;
          import javax.net.ssl.HttpsURLConnection;
          import javax.net.ssl.SSLSession;
          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory;

          public class ClientSendData {
              static Log log = LogFactory.getLog(ClientSendData.class);
              // 客戶端信任的證書
              private String sslTrustStore;
              private String sslTrustStorePassword;
              private String Url;

              //初始化數據
              public ClientSendData() {
                  sslTrustStore = "D:/ssl/clientTrust.jks";
                  sslTrustStorePassword = "123456";
                  Url = "https://test.yihaodian.com:8443/ims/feedbackToPingAn_getData.action";
              }

              public String sendData(String data) {
                  String receivedData = null;
                  try {
                      //設置系統參數
                      System.setProperty("javax.net.ssl.trustStore", sslTrustStore);
                      System.setProperty("javax.net.ssl.trustStorePassword",
                              sslTrustStorePassword);
                      receivedData = send(Url, data);
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                  return receivedData;
              }

              public static String send(String sendurl, String sendData)
                      throws Exception {
                  URL url = new URL(sendurl);
                  HostnameVerifier hv = new HostnameVerifier() {
                      public boolean verify(String urlHostName, SSLSession session) {
                          return true;
                      }
                  };
                  System.setProperty("java.protocol.handler.pkgs","sun.net.www.protocol");
                  HttpsURLConnection.setDefaultHostnameVerifier(hv);
                  Date current = new Date(System.currentTimeMillis());
                  log.info("begint to open connection at " + current);
                  HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
                  Date end = new Date(System.currentTimeMillis());
                  log.info("open connection ok at " + end + ",cost:"+ (end.getTime() - current.getTime()));
                  connection.setRequestProperty("Content-Type", "text/xml");
                  connection.setDoOutput(true);
                  connection.setDoInput(true);
                  connection.setRequestMethod("POST");
                  connection.setUseCaches(false);
                  connection.setReadTimeout(30000);
                  byte data[] = sendData.getBytes();
                  current = new Date(System.currentTimeMillis());
                  log.info("[SSLIX]notifyEai,begint to write data at " + current);
                  OutputStream out = connection.getOutputStream();
                  out.write(data);
                  end = new Date(System.currentTimeMillis());
                  log.info("write data ok at " + end + ",cost:"
                          + (end.getTime() - current.getTime()));
                  StringBuffer receivedData = new StringBuffer();
                  current = new Date(System.currentTimeMillis());
                  log.info("begint to read data at " + current);
                  InputStreamReader inReader = new InputStreamReader(connection
                          .getInputStream(), "UTF-8");
                  BufferedReader aReader = new BufferedReader(inReader);
                  String aLine;
                  while ((aLine = aReader.readLine()) != null) {
                      receivedData.append(aLine);
                  }
                  end = new Date(System.currentTimeMillis());
                  log.info("read data ok at " + end + ",cost:"
                          + (end.getTime() - current.getTime()));

                  log.info("開始返回狀態碼");
                  Integer statusCode = connection.getResponseCode();
                  log.info("返回狀態碼:" + statusCode);
                  aReader.close();
                  connection.disconnect();
                  return receivedData.toString();
              }

              public static void main(String[] args) {
                  ClientSendData t = new ClientSendData();
                  t.sendData("測試SSL單項連接,向服務端發送數據!");
              }
          }

          單項認證時,只需要設置客戶端信任的證書庫就行。但是當是雙向認證時,還需要設置客戶端密鑰庫密碼。

          HTTPS雙向驗證代碼如下:

          public class ClientSendData {
              static Log log = LogFactory.getLog(EaiChannel.class);
              //客戶端密鑰庫
              private String sslKeyStorePath;
              private String sslKeyStorePassword;
              private String sslKeyStoreType;
              // 客戶端信任的證書
              private String sslTrustStore;
              private String sslTrustStorePassword;
              private String eaiUrl;

              //初始化數據
              public ClientSendData() {
                  sslKeyStorePath = "D:/ssl/clientKeys.jks";
                  sslKeyStorePassword     = "123456";
                  sslKeyStoreType = "JKS"; //密鑰庫類型,有JKS PKCS12等
                  sslTrustStore = "D:/ssl/clientTrust.jks";
                  sslTrustStorePassword = "123456";
                  eaiUrl = "https://test.yihaodian.com:8443/ims/feedbackToPingAn_getData.action";
              }

              public String sendData(String data) {
                  String receivedData = null;
                  try {
                      
                       System.setProperty("javax.net.ssl.keyStore", sslKeyStorePath);
                       System.setProperty("javax.net.ssl.keyStorePassword",sslKeyStorePassword);
                       System.setProperty("javax.net.ssl.keyStoreType", sslKeyStoreType);
                      //設置系統參數
                      System.setProperty("javax.net.ssl.trustStore", sslTrustStore);
                      System.setProperty("javax.net.ssl.trustStorePassword",
                              sslTrustStorePassword);
                      receivedData = send(eaiUrl, data);
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                  return receivedData;
              }

              public static String send(String sendurl, String sendData)
                      throws Exception {
                  //和上面一樣
              }

              public static void main(String[] args) {
                  ClientSendData t = new ClientSendData();
                  t.sendData("測試SSL雙項連接,向服務端發送數據!");
              }
          }


          下面來說說可能會遇到的異常:

          1. java.security.NoSuchAlgorithmException

           

          一般來說是密鑰庫類型不對,如上面的sslKeyStoreType = "JKS" 卻寫成PKCS12。

           

          也有可能是證書的問題。

           

          2. java.net.UnknownHostException

           

          服務端地址不對。

           

          3.java.net.SocketException: Unexpected end of file from server

           

          這個異常和客戶端沒有關系,說明已經發送成功。是服務端的問題。有可能是防火墻的原因,也可能是服務端沒處理客戶端的響應。

          另外有人說當URL過長時也會發生此錯誤,當使用URL發送數據時,可以參考此意見。

           

          4.java.io.IOException:server returned HTTP response code :500

           

           

          這個異常是服務端代碼的問題。服務端相應代碼執行時拋出了異常。

           

           

          最后 如果返回的狀態碼是200 ,表示成功。


           

           

          posted on 2012-09-23 22:31 abin 閱讀(9149) 評論(1)  編輯  收藏 所屬分類: HTTPS

          Feedback

          # re: Java Https單向,雙向驗證 2013-03-18 13:32 suipy
          HostnameVerifier hv = new HostnameVerifier() {
          public boolean verify(String urlHostName, SSLSession session) {
          return true;
          }
          };
          .....
          HttpsURLConnection.setDefaultHostnameVerifier(hv);
          .....
          博主您好,這樣的重寫,把HTTPS默認的主機驗證給跳過了。
          例如,訪問百度的登錄頁面,應該是https://passport.baidu.com/v2/?login
          如果在瀏覽器輸入https://123.125.115.81/v2/?login
          就會報證書中subject的CN和輸入的域名不相符的異常(此時容易遭受中間人攻擊)。
          重寫該方法后,這種驗證就被覆蓋了,這種異常就不會捕獲,會有安全風險。

          您看看是不是這樣的?  回復  更多評論
            

          主站蜘蛛池模板: 武乡县| 高阳县| 天等县| 榆林市| 荃湾区| 綦江县| 周宁县| 六枝特区| 霍邱县| 萨嘎县| 瑞安市| 皮山县| 尤溪县| 城口县| 正镶白旗| 靖安县| 广东省| 资源县| 福贡县| 江口县| 邢台市| 永昌县| 双柏县| 中宁县| 彭阳县| 黄大仙区| 巩留县| 永昌县| 万宁市| 安仁县| 文登市| 阳原县| 思茅市| 宿迁市| 金昌市| 乌兰察布市| 南郑县| 集贤县| 宣恩县| 从江县| 吉木萨尔县|