少年阿賓

          那些青春的歲月

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks

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

           

          單項SSL連接,也就是只是客戶端驗證服務(wù)器證書。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;

              //初始化數(shù)據(jù)
              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 {
                      //設(shè)置系統(tǒng)參數(shù)
                      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("開始返回狀態(tài)碼");
                  Integer statusCode = connection.getResponseCode();
                  log.info("返回狀態(tài)碼:" + statusCode);
                  aReader.close();
                  connection.disconnect();
                  return receivedData.toString();
              }

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

          單項認(rèn)證時,只需要設(shè)置客戶端信任的證書庫就行。但是當(dāng)是雙向認(rèn)證時,還需要設(shè)置客戶端密鑰庫密碼。

          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;

              //初始化數(shù)據(jù)
              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);
                      //設(shè)置系統(tǒng)參數(shù)
                      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雙項連接,向服務(wù)端發(fā)送數(shù)據(jù)!");
              }
          }


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

          1. java.security.NoSuchAlgorithmException

           

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

           

          也有可能是證書的問題。

           

          2. java.net.UnknownHostException

           

          服務(wù)端地址不對。

           

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

           

          這個異常和客戶端沒有關(guān)系,說明已經(jīng)發(fā)送成功。是服務(wù)端的問題。有可能是防火墻的原因,也可能是服務(wù)端沒處理客戶端的響應(yīng)。

          另外有人說當(dāng)URL過長時也會發(fā)生此錯誤,當(dāng)使用URL發(fā)送數(shù)據(jù)時,可以參考此意見。

           

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

           

           

          這個異常是服務(wù)端代碼的問題。服務(wù)端相應(yīng)代碼執(zhí)行時拋出了異常。

           

           

          最后 如果返回的狀態(tài)碼是200 ,表示成功。


           

           

          posted on 2012-09-23 22:31 abin 閱讀(9151) 評論(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默認(rèn)的主機驗證給跳過了。
          例如,訪問百度的登錄頁面,應(yīng)該是https://passport.baidu.com/v2/?login
          如果在瀏覽器輸入https://123.125.115.81/v2/?login
          就會報證書中subject的CN和輸入的域名不相符的異常(此時容易遭受中間人攻擊)。
          重寫該方法后,這種驗證就被覆蓋了,這種異常就不會捕獲,會有安全風(fēng)險。

          您看看是不是這樣的?  回復(fù)  更多評論
            

          主站蜘蛛池模板: 梁河县| 尼勒克县| 桃园县| 邵武市| 四平市| 沭阳县| 探索| 盖州市| 鄱阳县| 万源市| 和田市| 青神县| 米易县| 修文县| 习水县| 南溪县| 咸丰县| 红安县| 枝江市| 柳江县| 阳新县| 景德镇市| 建湖县| 大同县| 富平县| 自贡市| 樟树市| 阿克苏市| 双桥区| 宁波市| 萨迦县| 龙泉市| 聂荣县| 友谊县| 小金县| 天镇县| 陈巴尔虎旗| 晋城| 房产| 铁力市| 来安县|