解决邮件javax.mail发送邮件的问题unable to find valid certification path to requested target

今天做项目时,困扰了我很长时间的邮件发送失败的问题终于被我找到啦!通过报错日志看到是PKIX path building failed ,最主要的报错还是unable to find valid certification path to requested target,我上网查了很多资料有的说是被杀毒软件拦截啦,我把360软件全部停止后还是不行,有的说没有相应的证书,但是也没有给出相应的证书,非常不解。后来终于找到了一篇文章靠点谱可以给出相应证书的生成,抱着试试看的态度试了试,发现问题解决啦!

引用@阿飞的文章如下:来源: http://blog.youkuaiyun.com/faye0412/article/details/6883879

这两天在twitter服务器上忽然遇到这样的异常:

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

经过检查确认,完整的异常信息应该如下:

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

后来到twitter开发者网站上去看到了也有人遇到了类似的问题,链接如下:https://dev.twitter.com/discussions/533

但是都没说明具体的解决方法,郁闷啊!!

在oracle某一博客上说是可以这样解决的:http://blogs.oracle.com/gc/entry/unable_to_find_valid_certification

但是悲催的是那个java类已经无法下载了。。。。历经N次的google,终于找到该文件了,不敢独享,记录于此。


问题的根本是:

缺少安全证书时出现的异常。

解决问题方法:

将你要访问的webservice/url....的安全认证证书导入到客户端即可。


以下是获取安全证书的一种方法,通过以下程序获取安全证书:

[java]  view plain  copy
  1. /* 
  2.  * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved. 
  3.  * 
  4.  * Redistribution and use in source and binary forms, with or without 
  5.  * modification, are permitted provided that the following conditions 
  6.  * are met: 
  7.  * 
  8.  *   - Redistributions of source code must retain the above copyright 
  9.  *     notice, this list of conditions and the following disclaimer. 
  10.  * 
  11.  *   - Redistributions in binary form must reproduce the above copyright 
  12.  *     notice, this list of conditions and the following disclaimer in the 
  13.  *     documentation and/or other materials provided with the distribution. 
  14.  * 
  15.  *   - Neither the name of Sun Microsystems nor the names of its 
  16.  *     contributors may be used to endorse or promote products derived 
  17.  *     from this software without specific prior written permission. 
  18.  * 
  19.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
  20.  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
  21.  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  22.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
  23.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  24.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
  25.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  26.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
  27.  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
  28.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
  29.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  30.  */  
  31.   
  32. import java.io.BufferedReader;  
  33. import java.io.File;  
  34. import java.io.FileInputStream;  
  35. import java.io.FileOutputStream;  
  36. import java.io.InputStream;  
  37. import java.io.InputStreamReader;  
  38. import java.io.OutputStream;  
  39. import java.security.KeyStore;  
  40. import java.security.MessageDigest;  
  41. import java.security.cert.CertificateException;  
  42. import java.security.cert.X509Certificate;  
  43.   
  44. import javax.net.ssl.SSLContext;  
  45. import javax.net.ssl.SSLException;  
  46. import javax.net.ssl.SSLSocket;  
  47. import javax.net.ssl.SSLSocketFactory;  
  48. import javax.net.ssl.TrustManager;  
  49. import javax.net.ssl.TrustManagerFactory;  
  50. import javax.net.ssl.X509TrustManager;  
  51.   
  52. public class InstallCert {  
  53.   
  54.     public static void main(String[] args) throws Exception {  
  55.         String host;  
  56.         int port;  
  57.         char[] passphrase;  
  58.         if ((args.length == 1) || (args.length == 2)) {  
  59.             String[] c = args[0].split(":");  
  60.             host = c[0];  
  61.             port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);  
  62.             String p = (args.length == 1) ? "changeit" : args[1];  
  63.             passphrase = p.toCharArray();  
  64.         } else {  
  65.             System.out  
  66.                     .println("Usage: java InstallCert <host>[:port] [passphrase]");  
  67.             return;  
  68.         }  
  69.   
  70.         File file = new File("jssecacerts");  
  71.         if (file.isFile() == false) {  
  72.             char SEP = File.separatorChar;  
  73.             File dir = new File(System.getProperty("java.home") + SEP + "lib"  
  74.                     + SEP + "security");  
  75.             file = new File(dir, "jssecacerts");  
  76.             if (file.isFile() == false) {  
  77.                 file = new File(dir, "cacerts");  
  78.             }  
  79.         }  
  80.         System.out.println("Loading KeyStore " + file + "...");  
  81.         InputStream in = new FileInputStream(file);  
  82.         KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());  
  83.         ks.load(in, passphrase);  
  84.         in.close();  
  85.   
  86.         SSLContext context = SSLContext.getInstance("TLS");  
  87.         TrustManagerFactory tmf = TrustManagerFactory  
  88.                 .getInstance(TrustManagerFactory.getDefaultAlgorithm());  
  89.         tmf.init(ks);  
  90.         X509TrustManager defaultTrustManager = (X509TrustManager) tmf  
  91.                 .getTrustManagers()[0];  
  92.         SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);  
  93.         context.init(nullnew TrustManager[] { tm }, null);  
  94.         SSLSocketFactory factory = context.getSocketFactory();  
  95.   
  96.         System.out  
  97.                 .println("Opening connection to " + host + ":" + port + "...");  
  98.         SSLSocket socket = (SSLSocket) factory.createSocket(host, port);  
  99.         socket.setSoTimeout(10000);  
  100.         try {  
  101.             System.out.println("Starting SSL handshake...");  
  102.             socket.startHandshake();  
  103.             socket.close();  
  104.             System.out.println();  
  105.             System.out.println("No errors, certificate is already trusted");  
  106.         } catch (SSLException e) {  
  107.             System.out.println();  
  108.             e.printStackTrace(System.out);  
  109.         }  
  110.   
  111.         X509Certificate[] chain = tm.chain;  
  112.         if (chain == null) {  
  113.             System.out.println("Could not obtain server certificate chain");  
  114.             return;  
  115.         }  
  116.   
  117.         BufferedReader reader = new BufferedReader(new InputStreamReader(  
  118.                 System.in));  
  119.   
  120.         System.out.println();  
  121.         System.out.println("Server sent " + chain.length + " certificate(s):");  
  122.         System.out.println();  
  123.         MessageDigest sha1 = MessageDigest.getInstance("SHA1");  
  124.         MessageDigest md5 = MessageDigest.getInstance("MD5");  
  125.         for (int i = 0; i < chain.length; i++) {  
  126.             X509Certificate cert = chain[i];  
  127.             System.out.println(" " + (i + 1) + " Subject "  
  128.                     + cert.getSubjectDN());  
  129.             System.out.println("   Issuer  " + cert.getIssuerDN());  
  130.             sha1.update(cert.getEncoded());  
  131.             System.out.println("   sha1    " + toHexString(sha1.digest()));  
  132.             md5.update(cert.getEncoded());  
  133.             System.out.println("   md5     " + toHexString(md5.digest()));  
  134.             System.out.println();  
  135.         }  
  136.   
  137.         System.out  
  138.                 .println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");  
  139.         String line = reader.readLine().trim();  
  140.         int k;  
  141.         try {  
  142.             k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;  
  143.         } catch (NumberFormatException e) {  
  144.             System.out.println("KeyStore not changed");  
  145.             return;  
  146.         }  
  147.   
  148.         X509Certificate cert = chain[k];  
  149.         String alias = host + "-" + (k + 1);  
  150.         ks.setCertificateEntry(alias, cert);  
  151.   
  152.         OutputStream out = new FileOutputStream("jssecacerts");  
  153.         ks.store(out, passphrase);  
  154.         out.close();  
  155.   
  156.         System.out.println();  
  157.         System.out.println(cert);  
  158.         System.out.println();  
  159.         System.out  
  160.                 .println("Added certificate to keystore 'jssecacerts' using alias '"  
  161.                         + alias + "'");  
  162.     }  
  163.   
  164.     private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();  
  165.   
  166.     private static String toHexString(byte[] bytes) {  
  167.         StringBuilder sb = new StringBuilder(bytes.length * 3);  
  168.         for (int b : bytes) {  
  169.             b &= 0xff;  
  170.             sb.append(HEXDIGITS[b >> 4]);  
  171.             sb.append(HEXDIGITS[b & 15]);  
  172.             sb.append(' ');  
  173.         }  
  174.         return sb.toString();  
  175.     }  
  176.   
  177.     private static class SavingTrustManager implements X509TrustManager {  
  178.   
  179.         private final X509TrustManager tm;  
  180.         private X509Certificate[] chain;  
  181.   
  182.         SavingTrustManager(X509TrustManager tm) {  
  183.             this.tm = tm;  
  184.         }  
  185.   
  186.         public X509Certificate[] getAcceptedIssuers() {  
  187.             throw new UnsupportedOperationException();  
  188.         }  
  189.   
  190.         public void checkClientTrusted(X509Certificate[] chain, String authType)  
  191.                 throws CertificateException {  
  192.             throw new UnsupportedOperationException();  
  193.         }  
  194.   
  195.         public void checkServerTrusted(X509Certificate[] chain, String authType)  
  196.                 throws CertificateException {  
  197.             this.chain = chain;  
  198.             tm.checkServerTrusted(chain, authType);  
  199.         }  
  200.     }  
  201.   
  202. }  

编译InstallCert.java,然后执行:java InstallCert hostname,比如:
java InstallCert www.twitter.com
会看到如下信息:

[java]  view plain  copy
  1. java InstallCert www.twitter.com  
  2. Loading KeyStore /usr/java/jdk1.6.0_16/jre/lib/security/cacerts...  
  3. Opening connection to www.twitter.com:443...  
  4. Starting SSL handshake...  
  5.   
  6. 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  
  7.     at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)  
  8.     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1476)  
  9.     at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)  
  10.     at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)  
  11.     at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:846)  
  12.     at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)  
  13.     at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)  
  14.     at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)  
  15.     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:815)  
  16.     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1025)  
  17.     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1038)  
  18.     at InstallCert.main(InstallCert.java:63)  
  19. Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target  
  20.     at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:221)  
  21.     at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:145)  
  22.     at sun.security.validator.Validator.validate(Validator.java:203)  
  23.     at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)  
  24.     at InstallCert$SavingTrustManager.checkServerTrusted(InstallCert.java:158)  
  25.     at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)  
  26.     at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:839)  
  27.     ... 7 more  
  28. Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target  
  29.     at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:236)  
  30.     at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:194)  
  31.     at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:216)  
  32.     ... 13 more  
  33.   
  34. Server sent 2 certificate(s):  
  35.   
  36.  1 Subject CN=www.twitter.com, O=example.com, C=US  
  37.    Issuer  CN=Certificate Shack, O=example.com, C=US  
  38.    sha1    2e 7f 76 9b 52 91 09 2e 5d 8f 6b 61 39 2d 5e 06 e4 d8 e9 c7   
  39.    md5     dd d1 a8 03 d7 6c 4b 11 a7 3d 74 28 89 d0 67 54   
  40.   
  41.  2 Subject CN=Certificate Shack, O=example.com, C=US  
  42.    Issuer  CN=Certificate Shack, O=example.com, C=US  
  43.    sha1    fb 58 a7 03 c4 4e 3b 0e e3 2c 40 2f 87 64 13 4d df e1 a1 a6   
  44.    md5     72 a0 95 43 7e 41 88 18 ae 2f 6d 98 01 2c 89 68   
  45.   
  46. Enter certificate to add to trusted keystore or 'q' to quit: [1]  

输入1,回车,然后会在当前的目录下产生一个名为“ ssecacerts” 的证书。

将证书拷贝到$JAVA_HOME/jre/lib/security目录下,或者通过以下方式:
System.setProperty("javax.net.ssl.trustStore", "你的jssecacerts证书路径");



注意:因为是静态加载,所以要重新启动你的Web Server,证书才能生效。

我注意到在我本地试着生成证书是不行的,因为域名没有解析,换成我们公司的测试环境地址生成就可以啦!
当你尝试从MATLAB中发送QQ邮件时遇到了错误提示 "unable to find valid certification path to requested target",这个问题通常是因为Java无法验证远程服务器SSL证书的有效性所导致的。对于QQ邮箱来说,默认情况下它使用了有效的公共信任链路下的数字证书,因此大多数时候这种问题是由于本地环境中缺失必要的CA根证书造成的。 为了修复此问题可以采取以下几个解决方案之一: ### 解决方案一:更新JVM版本 检查并升级您的系统上的 Java 运行环境至最新稳定版。有时旧版本可能存在已知的安全漏洞或是不再支持最新的加密标准协议等状况,而新的JDK/JRE则包含更多可信认证机构(CA) 的预安装列表以及更好的安全性增强特性。 ### 解决方案二:手动导入QQ邮箱的根证书 如果不想或不能更换整个Java运行环境,则可以选择将特定站点(这里是腾讯公司的域名)相关的中间件和/或自签发Root CA加入到当前使用的 JVM keystore 文件内: 1. 访问 [https://ssl.qlogo.cn](https://ssl.qlogo.cn),找到页面提供的下载链接获取“.crt”格式文件; 2. 打开命令提示符窗口执行下面这条指令完成对现有 cacerts 库的操作。(注意路径应指向实际存放位置) ```shell keytool -importcert -alias qqemail_root_ca -keystore "%JAVA_HOME%/lib/security/cacerts" -file /path/to/downloaded_cert_file.crt ``` 3. 默认口令通常是 `"changeit"` 。如果你不确定的话可以在执行之前先查看下具体值; 4. 最后重启 MATLAB 使其生效新加载的信任商店配置项。 ### 解决方案三:绕过SSL校验(仅限测试用途) 请注意这个办法并不推荐应用于生产部署当中因为它会使通信变得容易遭受中间人攻击(MITM attacks),但对于某些特殊情况确实能够快速解决问题: 更改原有连接部分为允许跳过错过的主机名匹配规则: ```matlab props.setProperty('mail.smtp.ssl.trust','*'); ... % 或者更激进的方式就是关闭所有安全层保护机制, props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.socketFactory.fallback", "false"); ``` 不过强烈建议只在内部网络环境下临时调试阶段这样做并且尽快恢复默认设置以免造成不必要的风险暴露点。 另外一种思路是利用第三方工具如Python脚本配合`smtplib`模块来替代原生Matlab mail函数处理这类场景,因为其灵活性更高也更容易维护管理外部依赖包。 --- 无论采用哪种途径都务必保证操作符合所在组织的信息安全管理规定和个人隐私政策法规的要求。 --
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值