leisure

          JAVA - exceed,helloworld
          隨筆 - 50, 文章 - 0, 評論 - 11, 引用 - 0
          數據加載中……

          java自動獲取安裝在線數字證書

          主要原理是:使用socket嘗試對目標服務器進行通信,如果通信失敗,證明沒有證書,不過此時的證書已悄悄發送到客戶端了。

          以前寫過這個工具類了:http://leisuredev.iteye.com/admin/blogs/714742
          今天稍微注釋并整理了一個版本:

            1 package com.leisure.cert;
            2 
            3 import java.io.File;
            4 import java.io.FileInputStream;
            5 import java.io.FileOutputStream;
            6 import java.io.InputStream;
            7 import java.io.OutputStream;
            8 import java.security.KeyStore;
            9 import java.security.cert.CertificateException;
           10 import java.security.cert.X509Certificate;
           11 
           12 import javax.net.ssl.HostnameVerifier;
           13 import javax.net.ssl.HttpsURLConnection;
           14 import javax.net.ssl.SSLContext;
           15 import javax.net.ssl.SSLSession;
           16 import javax.net.ssl.SSLSocket;
           17 import javax.net.ssl.SSLSocketFactory;
           18 import javax.net.ssl.TrustManager;
           19 import javax.net.ssl.TrustManagerFactory;
           20 import javax.net.ssl.X509TrustManager;
           21 
           22 /**
           23  * 
           24  * Java在線自動獲取并安裝證書工具類
           25  * @author Leisure
           26  * @version 1.1
           27  * 
           28  */
           29 public class CertManager {
           30 
           31     public static void main(String[] args) {
           32         try {
           33             trustCert("d:\\""www.google.com.hk"443"changeit");
           34         } catch (Exception e) {
           35             e.printStackTrace();
           36         }
           37     }
           38     
           39     /**
           40      * 
           41      * @param dir        證書所在路徑
           42      * @param host        主機地址
           43      * @param port        端口
           44      * @param password    證書密碼
           45      * @throws Exception
           46      */
           47     public static void trustCert(String dir, String host, int port, String password) throws Exception {
           48         // 如果證書頌給的名稱與所通信的域名不一致的話,那么需要重寫校驗方法
           49         HostnameVerifier hv = new HostnameVerifier() {
           50             @Override
           51             public boolean verify(String urlHostName, SSLSession session) {
           52                 return urlHostName.equals(session.getPeerHost());
           53             }
           54         };
           55         HttpsURLConnection.setDefaultHostnameVerifier(hv);
           56 
           57         // 信任管理器工廠
           58         TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
           59         File file = new File(dir + host + ".cer");
           60         file = makeSureFile(file);
           61         KeyStore ks = getKeyStore(file, password);
           62         tmf.init(ks);
           63         
           64         SSLContext context = SSLContext.getInstance("SSL");
           65         X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
           66         SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
           67         context.init(nullnew TrustManager[] { tm }, null);
           68         
           69         // 嘗試使用socket對目標主機進行通信
           70         SSLSocketFactory factory = context.getSocketFactory();        
           71         SSLSocket socket = (SSLSocket)factory.createSocket(host, port);
           72         socket.setSoTimeout(1000);
           73         try {
           74             // 如果直接通信沒問題的話,就不會報錯,也不必獲取證書
           75             // 如果報錯的話,很有可能沒有證書
           76             socket.startHandshake();
           77         } catch(Exception e) {
           78             e.printStackTrace();
           79         } finally {
           80             if(socket != null) {
           81                 try {
           82                     socket.close();
           83                 } catch(Exception e) {}        
           84                 socket = null;
           85             }
           86             X509Certificate[] chain = tm.getChain();
           87             if(chain != null) {
           88                 System.out.println("服務器返回:" + chain.length + " 個證書");
           89                 OutputStream out = null;
           90                 for(int i = 0; i < chain.length; i++) {
           91                     try {                        
           92                         X509Certificate x509Cert = chain[i];
           93                         String alias = host + (i > 0 ? i + "" : "");
           94                         ks.setCertificateEntry(alias, x509Cert);
           95                         
           96                         String certFile = dir + alias + ".cer";
           97                         out = new FileOutputStream(certFile);
           98                         ks.store(out, password.toCharArray());
           99                         out.close();
          100                         
          101                         System.setProperty("javax.net.ssl.trustStore", certFile);
          102                         System.out.println("" + (i + 1+ "個證書安裝成功");
          103                     } catch(Exception e) {
          104                         e.printStackTrace();
          105                         continue;
          106                     } finally {
          107                         try {
          108                             if(out != null) {
          109                                 out.close();
          110                             }
          111                             out = null;
          112                         } catch(Exception e) {}
          113                     }
          114                 }
          115             }
          116         }
          117     }
          118     
          119     /**
          120      * 確保文件存在
          121      * @param file
          122      * @return
          123      */
          124     private static File makeSureFile(File file) {
          125         if (file.isFile() == false) {
          126             char SEP = File.separatorChar;
          127             File dir = new File(System.getProperty("java.home"+ SEP + "lib"    + SEP + "security");
          128             file = new File(dir, file.getName());
          129             if (file.isFile() == false) {
          130                 file = new File(dir, "cacerts");
          131             }
          132         }
          133         return file;
          134     }
          135     
          136     /**
          137      * 獲取keystore
          138      * @param file
          139      * @param password
          140      * @return
          141      * @throws Exception
          142      */
          143     private static KeyStore getKeyStore(File file, String password) throws Exception {
          144         InputStream in = new FileInputStream(file);
          145         KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
          146         char[] passphrase = password.toCharArray();
          147         ks.load(in, passphrase);
          148         in.close();
          149         return ks;
          150     }
          151     
          152     public static class SavingTrustManager implements X509TrustManager {
          153         private final X509TrustManager tm;
          154         private X509Certificate[] chain;
          155 
          156         public SavingTrustManager(X509TrustManager tm) {
          157             this.tm = tm;
          158         }
          159         
          160         public X509TrustManager getTM() {
          161             return tm;
          162         }
          163         
          164         public X509Certificate[] getChain() {
          165             return chain;
          166         }
          167         
          168         public X509Certificate[] getAcceptedIssuers() {
          169             throw new UnsupportedOperationException();
          170         }
          171 
          172         public void checkClientTrusted(X509Certificate[] chain, String authType)
          173                 throws CertificateException {
          174             throw new UnsupportedOperationException();
          175         }
          176 
          177         public void checkServerTrusted(X509Certificate[] chain, String authType)
          178                 throws CertificateException {
          179             this.chain = chain;
          180             tm.checkServerTrusted(chain, authType);
          181         }
          182     }
          183 }
          184 

          posted on 2011-09-18 23:36 leisure 閱讀(2290) 評論(0)  編輯  收藏 所屬分類: java

          主站蜘蛛池模板: 石泉县| 观塘区| 东丽区| 咸宁市| 肃南| 宜宾县| 徐水县| 龙州县| 民和| 温州市| 宁远县| 邢台县| 司法| 巴东县| 铜鼓县| 仙游县| 五河县| 丹江口市| 桃江县| 邵东县| 沛县| 三河市| 甘谷县| 临洮县| 浮梁县| 大同市| 墨脱县| 涟水县| 卓尼县| 青浦区| 宣威市| 平乡县| 夏河县| 广宁县| 桃园县| 抚远县| 东海县| 溧阳市| 鸡东县| 长岭县| 汝阳县|