java开发https请求ssl不受信任问题解决方法
本文主要讨论的是java开发https请求ssl不受信任的解决方法,具体分析及实现代码如下。
在java代码中请求https链接的时候,可能会报下面这个错误
javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIXpathbuildingfailed:sun.security.provider.certpath.SunCertPathBuilderException:unabletofindvalidcertificationpathtorequestedtarget
原因是没有证书。在浏览器中直接使用url访问是可以的,应该是浏览器之前就保存过对应的.cer证书。
解决方法有两种,从目标机器获得有效证书或者忽略证书信任问题。
一、获得目标机器有效证书
1、编译安装证书程序javacInstallCert.java(代码如下)
/*
*Copyright2006SunMicrosystems,Inc.AllRightsReserved.
*
*Redistributionanduseinsourceandbinaryforms,withorwithout
*modification,arepermittedprovidedthatthefollowingconditions
*aremet:
*
*-Redistributionsofsourcecodemustretaintheabovecopyright
*notice,thislistofconditionsandthefollowingdisclaimer.
*
*-Redistributionsinbinaryformmustreproducetheabovecopyright
*notice,thislistofconditionsandthefollowingdisclaimerinthe
*documentationand/orothermaterialsprovidedwiththedistribution.
*
*-NeitherthenameofSunMicrosystemsnorthenamesofits
*contributorsmaybeusedtoendorseorpromoteproductsderived
*fromthissoftwarewithoutspecificpriorwrittenpermission.
*
*THISSOFTWAREISPROVIDEDBYTHECOPYRIGHTHOLDERSANDCONTRIBUTORS"AS
*IS"ANDANYEXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOTLIMITEDTO,
*THEIMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFORAPARTICULAR
*PURPOSEAREDISCLAIMED.INNOEVENTSHALLTHECOPYRIGHTOWNEROR
*CONTRIBUTORSBELIABLEFORANYDIRECT,INDIRECT,INCIDENTAL,SPECIAL,
*EXEMPLARY,ORCONSEQUENTIALDAMAGES(INCLUDING,BUTNOTLIMITEDTO,
*PROCUREMENTOFSUBSTITUTEGOODSORSERVICES;LOSSOFUSE,DATA,OR
*PROFITS;ORBUSINESSINTERRUPTION)HOWEVERCAUSEDANDONANYTHEORYOF
*LIABILITY,WHETHERINCONTRACT,STRICTLIABILITY,ORTORT(INCLUDING
*NEGLIGENCEOROTHERWISE)ARISINGINANYWAYOUTOFTHEUSEOFTHIS
*SOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOFSUCHDAMAGE.
*/
/**
*http://blogs.sun.com/andreas/resource/InstallCert.java
*Use:
*javaInstallCerthostname
*Example:
*%javaInstallCertecc.fedora.redhat.com
*/
importjavax.net.ssl.*;
importjava.io.*;
importjava.security.KeyStore;
importjava.security.MessageDigest;
importjava.security.cert.CertificateException;
importjava.security.cert.X509Certificate;
/**
*Classusedtoaddtheserver'scertificatetotheKeyStore
*withyourtrustedcertificates.
*/
publicclassInstallCert{
publicstaticvoidmain(String[]args)throwsException{
Stringhost;
intport;
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]);
Stringp=(args.length==1)?"changeit":args[1];
passphrase=p.toCharArray();
}else{
System.out.println("Usage:javaInstallCert[:port][passphrase]");
return;
}
Filefile=newFile("jssecacerts");
if(file.isFile()==false){
charSEP=File.separatorchar;
Filedir=newFile(System.getProperty("java.home")+SEP
+"lib"+SEP+"security");
file=newFile(dir,"jssecacerts");
if(file.isFile()==false){
file=newFile(dir,"cacerts");
}
}
System.out.println("LoadingKeyStore"+file+"...");
InputStreamin=newFileInputStream(file);
KeyStoreks=KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in,passphrase);
in.close();
SSLContextcontext=SSLContext.getInstance("TLS");
TrustManagerFactorytmf=
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
X509TrustManagerdefaultTrustManager=(X509TrustManager)tmf.getTrustManagers()[0];
SavingTrustManagertm=newSavingTrustManager(defaultTrustManager);
context.init(null,newTrustManager[]{
tm
}
,null);
SSLSocketFactoryfactory=context.getSocketFactory();
System.out.println("Openingconnectionto"+host+":"+port+"...");
SSLSocketsocket=(SSLSocket)factory.createSocket(host,port);
socket.setSoTimeout(10000);
try{
System.out.println("StartingSSLhandshake...");
socket.startHandshake();
socket.close();
System.out.println();
System.out.println("Noerrors,certificateisalreadytrusted");
}
catch(SSLExceptione){
System.out.println();
e.printStackTrace(System.out);
}
X509Certificate[]chain=tm.chain;
if(chain==null){
System.out.println("Couldnotobtainservercertificatechain");
return;
}
BufferedReaderreader=
newBufferedReader(newInputStreamReader(System.in));
System.out.println();
System.out.println("Serversent"+chain.length+"certificate(s):");
System.out.println();
MessageDigestsha1=MessageDigest.getInstance("SHA1");
MessageDigestmd5=MessageDigest.getInstance("MD5");
for(inti=0;i>4]);
sb.append(HEXDIGITS[b&15]);
sb.append('');
}
returnsb.toString();
}
privatestaticclassSavingTrustManagerimplementsX509TrustManager{
privatefinalX509TrustManagertm;
privateX509Certificate[]chain;
SavingTrustManager(X509TrustManagertm){
this.tm=tm;
}
publicX509Certificate[]getAcceptedIssuers(){
thrownewUnsupportedOperationException();
}
publicvoidcheckClientTrusted(X509Certificate[]chain,StringauthType)
throwsCertificateException{
thrownewUnsupportedOperationException();
}
publicvoidcheckServerTrusted(X509Certificate[]chain,StringauthType)
throwsCertificateException{
this.chain=chain;
tm.checkServerTrusted(chain,authType);
}
}
}
2、运行安装证书程序生成证书
javaInstallCertmy.hoolai.com
例如:javaInstalCertsmtp.zhangsan.com:465admin
如果不加参数password和host的端口号,上面的获取证书程序中默认给的端口号是:443,密码是:changeit
3、根据运行提示信息,输入1,回车,在当前目录下生成名为:jssecacerts的证书
将证书放置到$JAVA_HOME/jre/lib/security目录下,切记该JDK的jre是工程所用的环境!!!
或者:
System.setProperty("javax.net.ssl.trustStore","你的jssecacerts证书路径");
可以更改密码,在security目录下运行命令
keytool-storepasswd-newxxxcom-keystorecacerts
就可以修改密码,修改后使用命令
keytool-list-v-keystorecacerts
查看文件的信息,会提示需要密码才能查看,如果输入密码与修改后的密码匹配,说明修改成功了。
PS:至此这种方式可以成功使用ssl了,另外再补充一下,根据刚才生成的文件jssecacerts,可以生成cer文件,
命令如下
keytool-export-aliasxxx.com-1-keystorejssecacerts-rfc-filexxx.cer
如上,之前的工具类中默认命名别名是加上"-1"。使用InstallCert设置的密码需要跟cacerts文件中的密码一致,
如果修改过密码,就需要修改InstallCert类中对应的密码字符串,否则会有下面这个异常:
java.security.UnrecoverableKeyException:Passwordverificationfailed
二、忽略证书信任问题
源码:http://mengyang.iteye.com/blog/575671
一定要注意需要在connection创建之前调用文章里所述的方法,像这个样子:
trustAllHttpsCertificates();
HostnameVerifierhv=newHostnameVerifier(){
publicbooleanverify(StringurlHostName,SSLSessionsession){
returntrue;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
connection=(HttpURLConnection)url.openConnection();
好吧,两种方法都试过有效。
总结
以上就是本文关于java开发https请求ssl不受信任问题解决方法的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!