java自动获取安装在线数字证书
主要原理是:使用socket尝试对目标服务器进行通信,如果通信失败,证明没有证书,不过此时的证书已悄悄发送到客户端了。
以前写过这个工具类了: http://leisuredev.iteye.com/admin/blogs/714742
今天稍微注释并整理了一个版本:
以前写过这个工具类了: 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( null , new 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
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( null , new 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