java语言开发https请求ssl不受信任问题解决方法[Java代码]
龚超 2018-07-20 来源 : 阅读 1563 评论 0

摘要:本文主要向大家介绍了java语言开发https请求ssl不受信任问题解决方法,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了java语言开发https请求ssl不受信任问题解决方法,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

在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(代码如下)


/*

* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.

*

* Redistribution and use in source and binary forms, with or without

* modification, are permitted provided that the following conditions

* are met:

*

* - Redistributions of source code must retain the above copyright

* notice, this list of conditions and the following disclaimer.

*

* - Redistributions in binary form must reproduce the above copyright

* notice, this list of conditions and the following disclaimer in the

* documentation and/or other materials provided with the distribution.

*

* - Neither the name of Sun Microsystems nor the names of its

* contributors may be used to endorse or promote products derived

* from this software without specific prior written permission.

*

* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS

* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,

* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR

* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR

* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,

* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,

* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR

* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF

* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING

* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

/**

* //blogs.sun.com/andreas/resource/InstallCert.java

* Use:

* java InstallCert hostname

* Example:

*% java InstallCert ecc.fedora.redhat.com

*/

import javax.net.ssl.*;

import java.io.*;

import java.security.KeyStore;

import java.security.MessageDigest;

import java.security.cert.CertificateException;

import java.security.cert.X509Certificate;

/**

* Class used to add the server's certificate to the KeyStore

* with your trusted certificates.

*/

public class InstallCert {

public static void main(String[] args) throws Exception {

String host;

int port;

char[] passphrase;

if ((args.length == 1) || (args.length == 2)) {

String[] c = args[0].split(":");

host = c[0];

port = (c.length == 1) ? 443 : Integer.parseint(c[1]);

String p = (args.length == 1) ? "changeit" : args[1];

passphrase = p.toCharArray();

} else {

System.out.println("Usage: java InstallCert[:port] [passphrase]");

return;

}

File file = new File("jssecacerts");

if (file.isFile() == false) {

char SEP = File.separatorchar;

File dir = new File(System.getProperty("java.home") + SEP

+ "lib" + SEP + "security");

file = new File(dir, "jssecacerts");

if (file.isFile() == false) {

file = new File(dir, "cacerts");

}

}

System.out.println("Loading KeyStore " + file + "...");

InputStream in = new FileInputStream(file);

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());

ks.load(in, passphrase);

in.close();

SSLContext context = SSLContext.getInstance("TLS");

TrustManagerFactory tmf =

TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

tmf.init(ks);

X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];

SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);

context.init(null, new TrustManager[]{

tm

}

, null);

SSLSocketFactory factory = context.getSocketFactory();

System.out.println("Opening connection to " + host + ":" + port + "...");

SSLSocket socket = (SSLSocket) factory.createSocket(host, port);

socket.setSoTimeout(10000);

try {

System.out.println("Starting SSL handshake...");

socket.startHandshake();

socket.close();

System.out.println();

System.out.println("No errors, certificate is already trusted");

}

catch (SSLException e) {

System.out.println();

e.printStackTrace(System.out);

}

X509Certificate[] chain = tm.chain;

if (chain == null) {

System.out.println("Could not obtain server certificate chain");

return;

}

BufferedReader reader =

new BufferedReader(new InputStreamReader(System.in));

System.out.println();

System.out.println("Server sent " + chain.length + " certificate(s):");

System.out.println();

MessageDigest sha1 = MessageDigest.getInstance("SHA1");

MessageDigest md5 = MessageDigest.getInstance("MD5");

for (int i = 0; i < chain.length; i++) {

X509Certificate cert = chain[i];

System.out.println

(" " + (i + 1) + " Subject " + cert.getSubjectDN());

System.out.println(" Issuer " + cert.getIssuerDN());

sha1.update(cert.getEncoded());

System.out.println(" sha1 " + toHexString(sha1.digest()));

md5.update(cert.getEncoded());

System.out.println(" md5 " + toHexString(md5.digest()));

System.out.println();

}

System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");

String line = reader.readLine().trim();

int k;

try {

k = (line.length() == 0) ? 0 : Integer.parseint(line) - 1;

}

catch (NumberFormatException e) {

System.out.println("KeyStore not changed");

return;

}

X509Certificate cert = chain[k];

String alias = host + "-" + (k + 1);

ks.setCertificateEntry(alias, cert);

OutputStream out = new FileOutputStream("jssecacerts");

ks.store(out, passphrase);

out.close();

System.out.println();

System.out.println(cert);

System.out.println();

System.out.println

("Added certificate to keystore 'jssecacerts' using alias '"

+ alias + "'");

}

private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();

private static String toHexString(byte[] bytes) {

StringBuilder sb = new StringBuilder(bytes.length * 3);

for (int b : bytes) {

b &= 0xff;

sb.append(HEXDIGITS[b >> 4]);

sb.append(HEXDIGITS[b & 15]);

sb.append(' ');

}

return sb.toString();

}

private static class SavingTrustManager implements X509TrustManager {

private final X509TrustManager tm;

private X509Certificate[] chain;

SavingTrustManager(X509TrustManager tm) {

this.tm = tm;

}

public X509Certificate[] getAcceptedIssuers() {

throw new UnsupportedOperationException();

}

public void checkClientTrusted(X509Certificate[] chain, String authType)

throws CertificateException {

throw new UnsupportedOperationException();

}

public void checkServerTrusted(X509Certificate[] chain, String authType)

throws CertificateException {

this.chain = chain;

tm.checkServerTrusted(chain, authType);

}

}

}

复制代码

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

java InstallCert my.hoolai.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

二、忽略证书信任问题

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

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


trustAllHttpsCertificates();

HostnameVerifier hv = new HostnameVerifier() {

public boolean verify(String urlHostName, SSLSession session) {

return true;

}

};

HttpsURLConnection.setDefaultHostnameVerifier(hv);

connection = (HttpURLConnection) url.openConnection();

复制代码

好吧,两种方法都试过有效。

总结

以上就是本文关于java开发https请求ssl不受信任问题解决方法的全部内容,希望对大家有所帮助,了解更多内容,请关注职坐标编程语言JAVA频道!

本文由 @职坐标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论
本文作者 联系TA

擅长针对企业软件开发的产品设计及开发的细节与流程设计课程内容。座右铭:大道至简!

  • 370
    文章
  • 23295
    人气
  • 87%
    受欢迎度

已有23人表明态度,87%喜欢该老师!

进入TA的空间
求职秘籍 直通车
  • 索取资料 索取资料 索取资料
  • 答疑解惑 答疑解惑 答疑解惑
  • 技术交流 技术交流 技术交流
  • 职业测评 职业测评 职业测评
  • 面试技巧 面试技巧 面试技巧
  • 高薪秘笈 高薪秘笈 高薪秘笈
TA的其他文章 更多>>
WEB前端必须会的基本知识题目
经验技巧 93% 的用户喜欢
Java语言中四种遍历List的方法总结(推荐)
经验技巧 91% 的用户喜欢
Java语言之SHA-256加密的两种实现方法详解
经验技巧 75% 的用户喜欢
java语言实现把两个有序数组合并到一个数组的实例
经验技巧 75% 的用户喜欢
通过Java语言代码来创建view的方法
经验技巧 80% 的用户喜欢
其他海同师资 更多>>
吕益平
吕益平 联系TA
熟悉企业软件开发的产品设计及开发
孔庆琦
孔庆琦 联系TA
对MVC模式和三层架构有深入的研究
周鸣君
周鸣君 联系TA
擅长Hadoop/Spark大数据技术
范佺菁
范佺菁 联系TA
擅长Java语言,只有合理的安排和管理时间你才能做得更多,行得更远!
金延鑫
金延鑫 联系TA
擅长与学生或家长及时有效沟通
经验技巧30天热搜词 更多>>

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程