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不受信任问题解决方法的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!