注:网上搜来的快照,暂未验证

在java代码中请求https链接的时候,可能会报下面这个错误

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

原因是没有证书。在浏览器中直接使用url访问是可以的,应该是浏览器之前就保存过对应的.cer证书。

解决方法有两种,从目标机器获得有效证书或者忽略证书信任问题。

一、获得目标机器有效证书

1、编译安装证书程序 javac InstallCert.java(代码如下)

  1 /*
2
3 * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
4
5 *
6
7 * Redistribution and use in source and binary forms, with or without
8
9 * modification, are permitted provided that the following conditions
10
11 * are met:
12
13 *
14
15 * - Redistributions of source code must retain the above copyright
16
17 * notice, this list of conditions and the following disclaimer.
18
19 *
20
21 * - Redistributions in binary form must reproduce the above copyright
22
23 * notice, this list of conditions and the following disclaimer in the
24
25 * documentation and/or other materials provided with the distribution.
26
27 *
28
29 * - Neither the name of Sun Microsystems nor the names of its
30
31 * contributors may be used to endorse or promote products derived
32
33 * from this software without specific prior written permission.
34
35 *
36
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
38
39 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
40
41 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
44
45 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
46
47 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
48
49 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50
51 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
52
53 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
54
55 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
56
57 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58
59 */
60
61 /**
62
63 * http://blogs.sun.com/andreas/resource/InstallCert.java
64
65 * Use:
66
67 * java InstallCert hostname
68
69 * Example:
70
71 *% java InstallCert ecc.fedora.redhat.com
72
73 */
74
75 import javax.net.ssl.*;
76
77 import java.io.*;
78
79 import java.security.KeyStore;
80
81 import java.security.MessageDigest;
82
83 import java.security.cert.CertificateException;
84
85 import java.security.cert.X509Certificate;
86
87 /**
88
89 * Class used to add the server's certificate to the KeyStore
90
91 * with your trusted certificates.
92
93 */
94
95 public class InstallCert {
96
97 public static void main(String[] args) throws Exception {
98
99 String host;
100
101 int port;
102
103 char[] passphrase;
104
105 if ((args.length == 1) || (args.length == 2)) {
106
107 String[] c = args[0].split(":");
108
109 host = c[0];
110
111 port = (c.length == 1) ? 443 : Integer.parseint(c[1]);
112
113 String p = (args.length == 1) ? "changeit" : args[1];
114
115 passphrase = p.toCharArray();
116
117 } else {
118
119 System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
120
121 return;
122
123 }
124
125 File file = new File("jssecacerts");
126
127 if (file.isFile() == false) {
128
129 char SEP = File.separatorchar;
130
131 File dir = new File(System.getProperty("java.home") + SEP
132
133 + "lib" + SEP + "security");
134
135 file = new File(dir, "jssecacerts");
136
137 if (file.isFile() == false) {
138
139 file = new File(dir, "cacerts");
140
141 }
142
143 }
144
145 System.out.println("Loading KeyStore " + file + "...");
146
147 InputStream in = new FileInputStream(file);
148
149 KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
150
151 ks.load(in, passphrase);
152
153 in.close();
154
155 SSLContext context = SSLContext.getInstance("TLS");
156
157 TrustManagerFactory tmf =
158
159 TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
160
161 tmf.init(ks);
162
163 X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
164
165 SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
166
167 context.init(null, new TrustManager[]{
168
169 tm
170
171 }
172
173 , null);
174
175 SSLSocketFactory factory = context.getSocketFactory();
176
177 System.out.println("Opening connection to " + host + ":" + port + "...");
178
179 SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
180
181 socket.setSoTimeout(10000);
182
183 try {
184
185 System.out.println("Starting SSL handshake...");
186
187 socket.startHandshake();
188
189 socket.close();
190
191 System.out.println();
192
193 System.out.println("No errors, certificate is already trusted");
194
195 }
196
197 catch (SSLException e) {
198
199 System.out.println();
200
201 e.printStackTrace(System.out);
202
203 }
204
205 X509Certificate[] chain = tm.chain;
206
207 if (chain == null) {
208
209 System.out.println("Could not obtain server certificate chain");
210
211 return;
212
213 }
214
215 BufferedReader reader =
216
217 new BufferedReader(new InputStreamReader(System.in));
218
219 System.out.println();
220
221 System.out.println("Server sent " + chain.length + " certificate(s):");
222
223 System.out.println();
224
225 MessageDigest sha1 = MessageDigest.getInstance("SHA1");
226
227 MessageDigest md5 = MessageDigest.getInstance("MD5");
228
229 for (int i = 0; i < chain.length; i++) {
230
231 X509Certificate cert = chain[i];
232
233 System.out.println
234
235 (" " + (i + 1) + " Subject " + cert.getSubjectDN());
236
237 System.out.println(" Issuer " + cert.getIssuerDN());
238
239 sha1.update(cert.getEncoded());
240
241 System.out.println(" sha1 " + toHexString(sha1.digest()));
242
243 md5.update(cert.getEncoded());
244
245 System.out.println(" md5 " + toHexString(md5.digest()));
246
247 System.out.println();
248
249 }
250
251 System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
252
253 String line = reader.readLine().trim();
254
255 int k;
256
257 try {
258
259 k = (line.length() == 0) ? 0 : Integer.parseint(line) - 1;
260
261 }
262
263 catch (NumberFormatException e) {
264
265 System.out.println("KeyStore not changed");
266
267 return;
268
269 }
270
271 X509Certificate cert = chain[k];
272
273 String alias = host + "-" + (k + 1);
274
275 ks.setCertificateEntry(alias, cert);
276
277 OutputStream out = new FileOutputStream("jssecacerts");
278
279 ks.store(out, passphrase);
280
281 out.close();
282
283 System.out.println();
284
285 System.out.println(cert);
286
287 System.out.println();
288
289 System.out.println
290
291 ("Added certificate to keystore 'jssecacerts' using alias '"
292
293 + alias + "'");
294
295 }
296
297 private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
298
299 private static String toHexString(byte[] bytes) {
300
301 StringBuilder sb = new StringBuilder(bytes.length * 3);
302
303 for (int b : bytes) {
304
305 b &= 0xff;
306
307 sb.append(HEXDIGITS[b >> 4]);
308
309 sb.append(HEXDIGITS[b & 15]);
310
311 sb.append(' ');
312
313 }
314
315 return sb.toString();
316
317 }
318
319 private static class SavingTrustManager implements X509TrustManager {
320
321 private final X509TrustManager tm;
322
323 private X509Certificate[] chain;
324
325 SavingTrustManager(X509TrustManager tm) {
326
327 this.tm = tm;
328
329 }
330
331 public X509Certificate[] getAcceptedIssuers() {
332
333 throw new UnsupportedOperationException();
334
335 }
336
337 public void checkClientTrusted(X509Certificate[] chain, String authType)
338
339 throws CertificateException {
340
341 throw new UnsupportedOperationException();
342
343 }
344
345 public void checkServerTrusted(X509Certificate[] chain, String authType)
346
347 throws CertificateException {
348
349 this.chain = chain;
350
351 tm.checkServerTrusted(chain, authType);
352
353 }
354
355 }
356
357 }

2、运行安装证书程序生成证书

java InstallCert www.xxx.com

例如:java InstalCert smtp.zhangsan.com:465 admin
如果不加参数password和host的端口号,上面的获取证书程序中默认给的端口号是:443,密码是:changeit

3、根据运行提示信息,输入1,回车,在当前目录下生成名为: jssecacerts 的证书

将证书放置到$JAVA_HOME/jre/lib/security目录下, 切记该JDK的jre是工程所用的环境!!!

或者:

System.setProperty("javax.net.ssl.trustStore", "你的jssecacerts证书路径");

可以更改密码,在security目录下运行命令

keytool -storepasswd -new xxxcom -keystore cacerts

就可以修改密码,修改后使用命令

keytool -list -v -keystore cacerts

查看文件的信息,会提示需要密码才能查看,如果输入密码与修改后的密码匹配,说明修改成功了。

PS:至此这种方式可以成功使用ssl了,另外再补充一下,根据刚才生成的文件jssecacerts,可以生成cer文件,

命令如下

keytool -export -alias xxx.com-1 -keystore jssecacerts -rfc -file xxx.cer

如上,之前的工具类中默认命名别名是加上"-1"。使用InstallCert设置的密码需要跟cacerts文件中的密码一致,

如果修改过密码,就需要修改InstallCert类中对应的密码字符串,否则会有下面这个异常:

java.security.UnrecoverableKeyException: Password verification failed

二、忽略证书信任问题

源码:http://mengyang.iteye.com/blog/575671

一定要注意需要在connection创建之前调用文章里所述的方法,像这个样子:

trustAllHttpsCertificates();

HostnameVerifier hv = new HostnameVerifier() {

    public boolean verify(String urlHostName, SSLSession session) {

      return true;

    }

  };
    

trustAllHttpsCertificates();

HostnameVerifier hv = new HostnameVerifier() {

    public boolean verify(String urlHostName, SSLSession session) {

      return true;

    }

  };

HttpsURLConnection.setDefaultHostnameVerifier(hv);

connection = (HttpURLConnection) url.openConnection();

最新文章

  1. 便于开发的Helper类
  2. &lt;input type=&quot;file&quot;&gt; change事件异常处理办法
  3. 怎样运用好ZBrush中的布尔运算
  4. SPOJ 3273
  5. requestAnimationFrame 动画
  6. Asp.net MVC Razor Generator
  7. &quot;_Default&quot;同时存在于两个dll文件中的解决办法
  8. 【UNIX网络编程(二)】基本TCP套接字编程函数
  9. HDU4565 &amp;&amp; 2013年长沙邀请赛A题
  10. JavaScript与WebAssembly进行比较
  11. Bigger-Mai 养成计划,Python基础巩固二
  12. C#: int 与 byte[] 互转
  13. P4248 [AHOI2013]差异
  14. HTTP参数污染【转】
  15. Verilog 加法器和减法器(6)
  16. Laravel validate 500异常 添加手机验证,中文验证与Validator验证的“半个”生命周期
  17. Google想出了一个决定人员晋升的算法,然后就没有然后了......
  18. 如何解决input file 选取相同文件后,change事件不起作用解决方法
  19. node.js学习笔记(一)——创建第一个应用
  20. #1490 : Tree Restoration-(微软2017在线笔试)

热门文章

  1. inno steup 安装判断 进程是否运行
  2. 遗传算法(Genetic Algorithm)——基于Java实现
  3. leetcode110:combination-sum-ii
  4. C++实现学校运动会管理系统
  5. C++ 基础 3:类和对象
  6. springboot mybatis保存数据中文保存成???
  7. &lt;摘自&gt;飞:jxl简析2 [ http://www.emlog.net/fei ]
  8. jdk的动态代理和静态代理你还写不出来嘛???
  9. 通过ip访问项目
  10. 【老孟Flutter】自定义文本步进组件